Spring 循环依赖时,对需要AOP中增强的类如何处理?
程序员文章站
2022-04-18 13:53:04
...
Spring 5.1.8 RELEASE
例:
@Aspect
@Component
public class LogAspects {
//抽取公共的切入点表达式
//1、本类引用
//2、其他的切面引用
@Pointcut("execution(public int com.aop.MathCalculator.*(..))")
public void pointCut(){};
//@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"运行。。。@Before:参数列表是:{"+Arrays.asList(args)+"}");
}
@After("com.atguigu.aop.LogAspects.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"结束。。。@After");
}
//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
@AfterThrowing(value="pointCut()",throwing="exception")
public void logException(JoinPoint joinPoint,Exception exception){
System.out.println(""+joinPoint.getSignature().getName()+"异常。。。异常信息:{"+exception+"}");
}
}
@Component
public class MathCalculator {
@Autowired
private AOPTest aopTest;
public int div(int i,int j){
System.out.println("MathCalculator...div...");
return i/j;
}
}
@Component
public class AOPTest {
@Autowired
private MathCalculator mathCalculator;
}
请大家考虑一个问题:
正常属性依赖注入的时候,如何解决循环依赖?
主要方式,通过在实例化完成之后将实例加入到singletonFactories中,后边的处理就是对实例进行赋值和初始化。比如:A依赖B,B依赖A。在A填充属性的时候获取依赖的Bean B。在这个时候B发现依赖着A,这个时候获取A就从singletonFactories获取出来进行返回赋值,从而解决循环依赖的问题。
但是对于AOP需要增强的Bean应该如何处理循环依赖的问题?
在实例话之前,AOP增强的Bean和普通的Bean没有什么区别,加入到singletonFactories之后。当有其他Bean依赖此Bean的时候,就需要获取Bean的实例,都要调用
getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean);
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
在内部都调用了实现SmartInstantiationAwareBeanPostProcessor接口的处理器。
其中有一个处理器,AnnotationAwareAspectJAutoProxyCreator的父类AbstractAutoProxyCreator实现了SmartInstantiationAwareBeanPostProcessor。
下面我们将来分析一下此处理器对Bean的不同的处理
AbstractAutoProxyCreator#getEarlyBeanReference
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
//主要作用,提前给依赖的Bean返回一个代理对象,在初始化完成之后不用再次调用了。
return wrapIfNecessary(bean, beanName, cacheKey);
}
增强的过程具体详见后续文章:SpringAOP的实现原理
所以在Bean依赖处理的时候就会将AOP增强的Bean就增强了,不需要等到初始化完成之后。