欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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就增强了,不需要等到初始化完成之后。