26.AOP的第三个时机之循环依赖过程中

116 阅读15分钟

AOP肯定是跟bean的实例化息息相关的,注意,我说的是实例化,而不是生命周期。也就是说,我们AOP肯定是在bean实例化好了后再进行动态代理,想想JDK的动态代理,是需要一个实例化的被代理对象的。

如果你的类被别的类依赖了,那么在依赖获取的过程中进行AOP动态代理。

循环依赖示例代码

先定义2个接口

package circle;

public interface LogService {

     void log();
}
package circle;

public interface PrintService {

     void print();
}

再定义1个切面

package circle;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class Aop implements PriorityOrdered {

    //指定切入点表达式,拦截那些方法,即为那些类生成代理对象
    //@Pointcut("execution(* com.aop.UserDao.save(..))")  ..代表所有参数
    //@Pointcut("execution(* com.aop.UserDao.*())")  指定所有的方法
    //@Pointcut("execution(* com.aop.UserDao.save())") 指定save方法

    @Pointcut("execution(* circle.*.*(..))")
    public void pointCut(){

    }

    @Before("pointCut()")
    public void Before(){
        System.out.println("Before");
    }

    @After("pointCut()")
    public void After(){
        System.out.println("After");
    }

    @AfterThrowing("pointCut()")
   public void AfterThrowing(){
      System.out.println("AfterThrowing");
   }

   @AfterReturning("pointCut()")
   public void AfterReturning(){
      System.out.println("AfterReturning");
   }

   @Around("pointCut()")
   public void Around(ProceedingJoinPoint joinPoint) throws Throwable {
      System.out.println("Around Before");
      joinPoint.proceed();
      System.out.println("Around After");
   }

   @Override
   public int getOrder() {
      return 1;
   }
}

定义接口的实现类A和B,也是循环依赖的2个类。

package circle;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("a")
public class A implements LogService  {

   @Autowired
   private PrintService b;

   @Override
   public void log() {
      System.out.println(b);
      System.out.println("log");
   }
}
package circle;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("b")
public class B   implements PrintService{

   @Autowired
   private LogService a;

   @Override
   public void print() {
      System.out.println(a);
      System.out.println("print");
   }
}

测试类

package circle;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestCircleCondition {
   public static void main(String[] args) {
      /**
       * 创建一个BeanDefinition读取器 根据注解读取
       * 创建一个BeanDefinition扫描器 能够扫描一个类或者包 转换成bd
       **/
      AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
      //注册配置类
      context.register(BeanConfig.class);
      context.refresh();
      LogService a = context.getBean("a", LogService.class);
      a.log();

      PrintService b = context.getBean("b", PrintService.class);

      b.print();
   }
}

循环依赖的过程回顾

 A、B 类 setter 循环依赖的创建过程
 
1.getSingleton("a", true) 获取a,会从一级缓存中找a(一级缓存该bean为空且当前 bean 正在创建才能去2级缓存拿),然后直接返回空,此时 3 个级别的缓存中都没有 a

2.调用getSingleton(String, ObjectFactory),ObjectFactory是调用createBean方法
sharedInstance = getSingleton(beanName, 
                                () -> {
                                    return createBean(beanName, mbd, args);
                                });

3.将a添加到正在创建的集合singletonsCurrentlyInCreation中

4.调用 ObjectFactory.getObject()即createBean方法

5.进入doCreateBean方法,推断构造方法、反射调用构造方法实例化bean,这个时候a对象是早期的a,属于半成品。

6.判断需要提前暴露 加入三级缓存放入的是SingletonFactory,SingletonFactory有半成品的引用:
    addSingletonFactory(beanName,
                    () -> getEarlyBeanReference(beanName, mbd, bean));

7.调用 populateBean方法,为a做属性填充操作,注入依赖的对象,发现 setB 需要注入b

8.调用getSingleton(String, ObjectFactory),ObjectFactory是调用createBean方法
sharedInstance = getSingleton(beanName, 
                                () -> {
                                    return createBean(beanName, mbd, args);
                                });

9.将b添加到正在创建的集合singletonsCurrentlyInCreation中

10.调用 ObjectFactory.getObject()即createBean方法

11.进入doCreateBean方法,反射调用构造方法实例化b,这个时候b对象是早期的b,属于半成品

12.判断需要提前暴露 加入三级缓存:addSingletonFactory(beanName,
                    () -> getEarlyBeanReference(beanName, mbd, bean));

13.调用populateBean方法,为b做属性填充操作,注入依赖的对象,发现 setA 需要注入a

14.调用 getSingleton("a", true) 获取a,会从3级缓存中找a。
一级缓存该bean为空且当前 bean 正在创建才能去2级缓存拿,2级缓存是空。
2级缓存是空并且允许循环依赖才能从3级缓存拿。
从3级缓存中获取调用ObjectFactory
然后调用ObjectFactory#getObject获取bean。
即调用getEarlyBeanReference方法获取a。
在获取a的时候会提前获取a的代理对象
在获取a的时候会提前获取a的代理对象
在获取a的时候会提前获取a的代理对象
    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        //1.不是合成的
        //2.存在InstantiationAwareBeanPostProcessor
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp
                            = (SmartInstantiationAwareBeanPostProcessor) bp;
                    //AbstractAutoProxyCreator.getEarlyBeanReference
                    exposedObject 
                            = ibp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
        }
        return exposedObject;
    }

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        this.earlyProxyReferences.put(cacheKey, bean);
        return wrapIfNecessary(bean, beanName, cacheKey);
    }

此时 a 会从第 3 级缓存中被移到第 2 级缓存,然后将其返回给 b 使用,此时 a 是个半成品(属性还未填充完毕)3级缓存是个工厂,工厂创建对象完毕就没用了,所以需要从三级缓存移除,加入二级缓存
 
15.b 通过 setA 将 14 中获取的 a 注入到 b 中,b填充属性完毕 然后调用
b= initializeBean("b", b, mbd)

initializeBean方法流程如下:
1.invokeAwareMethods,设置Spring的上下文组件
2.BeanPostProcessor 的 before 方法
3.invokeInitMethods
4.BeanPostProcessor 的 after 方法
    
16.调用Object earlySingletonReference = getSingleton(beanName, false);
即getSingleton("b", false)获取b,注意这个时候第二个参数是false,这个参数为 false 的时候,只会从前 2 级缓存中尝试获取b,此时1级缓存 2级缓存都没有,只有3级缓存有1个工厂对象,所以获取的是空。

注意:如果不是空会判断initializeBean("b", b, mbd)返回的对象和getSingleton("b", false)获取的对象是不是1个对象。因为对b进行处理完毕,可能对b进行改变,有可能导致b和原始的b不是同一个对象了。
所以需要判断提前暴露的b和原始的b是不是一个对象。

虽然b没有做判断但是a在二级缓存是存在的。所以a做了这个判断判断。

这里最后的返回的是 initializeBean("b", b, mbd)方法返回的对象
此时b创建完毕 最后b会从第2 3级缓存中被移除,然后被丢到1级缓存

注意b没有进入二级缓存
注意b没有进入二级缓存
注意b没有进入二级缓存

17.b 返回给 a,然后 b 被通过 A 类中的 setB 注入给 a

18.a 的 populateBean 执行完毕,即:完成属性填充,到此时 a 已经注入到 b 中了

19.调用a= initializeBean("a", a, mbd)对 a 进行处理,这个内部可能对 a 进行改变,有可能导致 a 和原始的 a 不是同一个对象了
1.invokeAwareMethods,设置Spring的上下文组件
2.BeanPostProcessor 的 before 方法
3.invokeInitMethods
4.BeanPostProcessor 的 after 方法

20.调用getSingleton("a", false)获取 a,注意这个时候第二个参数是 false,这个参数为 false 的时候,只会从前 2 级缓存中尝试获取 a,而 a 在步骤 11 中已经被丢到了第 2 级缓存中,所以此时这个可以获取到 a,这个 a 已经被注入给 b 了。

因为对a进行处理完毕,可能对a进行改变,有可能导致a和原始的a不是同一个对象了。所以需要判断提前暴露的a和原始的a是不是一个对象。
所以这里最后的返回的是 initializeBean("a", a, mbd) 的对象
此时a创建完毕 最后a会从第2 3级缓存中被移除,然后被丢到1级缓存

21.此时判断注入给 b 的 a 和通过initializeBean方法产生的 a 是否是同一个 a,不是同一个,则弹出异常

22.此时a创建完毕 最后b会从第2 3级缓存中被移除,然后被丢到1级缓存

循环依赖过程中的AOP

对照上面的循环依赖过程,稍微走读一下代码。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   }
   if (instanceWrapper == null) {
      /***
       * 创建bean实例 仅仅是创建bean实例
       * 1.判断是否存在Supplier和Factory-Method如果有那么就使用并创建实例
       *  否则就选择使用构造函数进行构造
       * 2.计算构造函数至少有几个参数 选择构造函数
       * 3.选择构造函数的参数 下标&通用
       * 4.计算构造函数的参数权重
       * instanceWrapper实现了 ConfigurablePropertyAccessor
       * 是一个包装类 该类的属性可以编辑
       * instanceWrapper有一个属性WrappedInstance 里面放的就是我们构造的实例
       */
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   }
   Object bean = instanceWrapper.getWrappedInstance();
   Class<?> beanType = instanceWrapper.getWrappedClass();
   if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
   }

   // Allow post-processors to modify the merged bean definition.
   //允许  post-processors 修改 beanDefinition
   //这里都已经构造完了实例 在修改beanDefinition 有什么意义呢?
   synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
         try {
            //调用 MergedBeanDefinitionPostProcessor
            //查找出满足条件的属性、方法, 将他们封装起来, 以便后面在填充属性的时候可以直接使用
            //https://juejin.cn/post/6844904167945797640
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         }
         catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         }
         mbd.postProcessed = true;
      }
   }

   // Eagerly cache singletons to be able to comresolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   /***
    * 是否需要提前暴露
    * 判断条件:
    * 1.是单例
    * 2.允许循环依赖
    * 3.bean正在被创建
    */
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
   //需要提前暴露
   if (earlySingletonExposure) {
      if (logger.isTraceEnabled()) {
         logger.trace("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      }
      /***
       * singletonObjects 一级缓存池
       * earlySingletonObjects 二级缓存池
       * singletonFactories 三级缓存池
       * 将ObjectFactory<?> singletonFactory 加入三级缓存 singletonFactories
       */
       //getEarlyBeanReference放入了提前实例化但是未初始化的对象
       //getEarlyBeanReference中获取了所有的SmartInstantiationAwareBeanPostProcessor并调用
       //SmartInstantiationAwareBeanPostProcessor中getEarlyBeanReference是一个默认方法
       //默认返回的是传入的bean
      addSingletonFactory( beanName,() -> getEarlyBeanReference(beanName, mbd, bean));
   }

   // Initialize the bean instance.
   //这个bean已经放入了 getEarlyBeanReference(beanName, mbd, bean)
   Object exposedObject = bean;
   try {
      /***
       * 1.属性填充
       * 2.处理属性依赖
       * 传入的是 BeanWrapper
       */
      populateBean(beanName, mbd, instanceWrapper);
      
      /***
       * 初始化bean
       * 如果bean实现了以下接口
       * BeanNameAware, BeanFactoryAware, ApplicationContextAware
       * 则调用对应接口的方法
       * 注意最后bean的代理对象就是在这里被创建的
       */
      exposedObject = initializeBean(beanName, exposedObject, mbd);
   }
   catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
         throw (BeanCreationException) ex;
      }
      else {
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
   }
   /***
    * 是否需要提前暴露 earlySingletonExposure = true
    * 判断条件:
    * 1.是单例
    * 2.允许循环依赖
    * 3.bean正在被创建
    */
   if (earlySingletonExposure) {
      // A 和 B 循环依赖
      // 对于A来说
      // 如果没有循环依赖不会从三级缓存获取 这里直接返回空
      // 如果没有循环依赖 返回空 因为allowEarlyReference是false 所以不会不到三级缓存拿
      // 如果有循环依赖 在B填充属性A对象时 会在填充属性的方法中调用 getSingleton(beanName, true);
      // 因为allowEarlyReference是true 所以会到三级缓存拿 并放入二级缓存
      // 然后在这里获取的就是二级缓存中的对象

      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) {
         //判断代理的对象和提前暴露的对象是不是还是一个 注意使用的是 ==
         if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
         //如果不是一个判断是否有依赖该bean的对象
         }else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                  actualDependentBeans.add(dependentBean);
               }
            }
            //如果有抛出异常
            if (!actualDependentBeans.isEmpty()) {
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            }
         }
      }
   }

   // Register bean as disposable.
   try {
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

在创建A的实例的时候调用了doCreateBean方法。

1.createBeanInstance(beanName, mbd, args);创建了A的实例

2.addSingletonFactory( beanName,() -> getEarlyBeanReference(beanName, mbd, bean));将A的实例放了三级缓存,其中bean就是A的实例

3.populateBean(beanName, mbd, instanceWrapper);为A的实例填充属性,instanceWrapper是A的实例的包装对象。

4.在populateBean(beanName, mbd, instanceWrapper);方法中有如下代码:

for (BeanPostProcessor bp : getBeanPostProcessors()) {
   if (bp instanceof InstantiationAwareBeanPostProcessor) {
      InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
      PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
      if (pvsToUse == null) {
         if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
         }
         pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
         if (pvsToUse == null) {
            return;
         }
      }
      pvs = pvsToUse;
   }
}

遍历InstantiationAwareBeanPostProcessor,其中有1个AutowiredAnnotationBeanPostProcessor。

它的postProcessProperties方法如下

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
   InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
   try {
     /***
     metadata = {InjectionMetadata@2239} 
         targetClass = {Class@1785} "class circle.A"
         injectedElements = {ArrayList@2272}  size = 1
              0 ="AutowiredFieldElement for private circle.PrintService circle.A.b"
                  number = {Field@2262}private circle.PrintService circle.A.b
         checkedElements = {LinkedHashSet@2268}  size = 1
              0 ="AutowiredFieldElement for private circle.PrintService circle.A.b"
                  number = {Field@2262}private circle.PrintService circle.A.b
     ***/
      metadata.inject(bean, beanName, pvs);
   }
   catch (BeanCreationException ex) {
      throw ex;
   }
   catch (Throwable ex) {
      throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
   }
   return pvs;
}

可以看到A实例需要自动装配的字段是b,此时会遍历所有的element依次resolve即解决装配。

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
   Collection<InjectedElement> checkedElements = this.checkedElements;
   Collection<InjectedElement> elementsToIterate =
         (checkedElements != null ? checkedElements : this.injectedElements);
   if (!elementsToIterate.isEmpty()) {
      for (InjectedElement element : elementsToIterate) {
         if (logger.isTraceEnabled()) {
            logger.trace("Processing injected element of bean '" + beanName + "': " + element);
         }
         element.inject(target, beanName, pvs);
      }
   }
}

element.inject(target, beanName, pvs);最后会调用DependencyDescriptor#resolveCandidate

public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory)
      throws BeansException {

   return beanFactory.getBean(beanName);
}

此时beanFactory.getBean(beanName);触发B的实例化和初始化

在创建B的实例的时候调用了doCreateBean方法。

1.createBeanInstance(beanName, mbd, args);创建了B的实例

2.addSingletonFactory( beanName,() -> getEarlyBeanReference(beanName, mbd, bean));将B的实例放了三级缓存,其中bean就是B的实例

3.populateBean(beanName, mbd, instanceWrapper);为B的实例填充属性,instanceWrapper是B的实例的包装对象。

然后开始B实例需要自动装配的字段是b,此时会遍历所有的element依次resolve即解决装配。

最后在DependencyDescriptor#resolveCandidate方法中调用beanFactory.getBean(beanName);寻找A。

这里的参数name是a。

@Override
public Object getBean(String name) throws BeansException {
   return doGetBean(name, null, null, false);
}

参数allowEarlyReference=true

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
   /**
    * 这个singletonObjects就是微观层面的IOC容器,循环创建刚开始时,IOC确实是空的。
    * 但是我前面一开始的getBean()方法是存在递归调用现象的直接举2个例子:
    * 第一:假如现在在实例化A,结果有发现需要给A注入B,
    * 那Spring是不是得获得B,怎么获得呢? 递归使用getBean(BName)完成,
    * 第二个例子: A被添加上了@Lazy注解,是懒加载的,但是终究有一个会通过getBean(AName)获取A,
    * 这是发现A是实例化需要B,B肯定已经实例化完事了,同样是通过递归getBean(BName)实现注入,
    * 在这两个过程中就是getSingleton()保证不会重复创建已经存在的实例
    */
   //是否应创建早期引用 allowEarlyReference is true
   Object singletonObject = this.singletonObjects.get(beanName);
   //一级缓存中该bean为空 且 当前 bean 正在创建才能去2级缓存拿
   if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      //2级缓存中获取
      singletonObject = this.earlySingletonObjects.get(beanName);
      if (singletonObject == null && allowEarlyReference) {
         synchronized (this.singletonObjects) {
            // Consistent creation of early reference within full singleton lock
            singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
               singletonObject = this.earlySingletonObjects.get(beanName);
               if (singletonObject == null) {
                  //3级缓存中获取 获取的是一个ObjectFactory
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                     //调用ObjectFactory的getObject方法获取对象
                     singletonObject = singletonFactory.getObject();
                     //放入2级缓存
                     this.earlySingletonObjects.put(beanName, singletonObject);
                     //从3级缓存移除
                     this.singletonFactories.remove(beanName);
                  }
               }
            }
         }
      }
   }
   return singletonObject;
}

先从一级缓存和二级缓存中拿a,没拿到会从三级缓存中拿a。三级缓存是1个ObjectFactory。

调用ObjectFactory的getObject方法获取对象a。

ObjectFactory的getObject方法对应的是getEarlyBeanReference方法。

//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) {
            //AbstractAutoProxyCreator.getEarlyBeanReference
            SmartInstantiationAwareBeanPostProcessor ibp 
                        = (SmartInstantiationAwareBeanPostProcessor) bp;
            exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
        }
    }
}
return exposedObject;
}

调用AnnotationAwareAspectJAutoProxyCreator#getEarlyBeanReference

最后调用的是AbstractAutoProxyCreator#getEarlyBeanReference

@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
   Object cacheKey = getCacheKey(bean.getClass(), beanName);
   this.earlyProxyReferences.put(cacheKey, bean);
   //创建代理的开始
   return wrapIfNecessary(bean, beanName, cacheKey);
}

最后wrapIfNecessary(bean, beanName, cacheKey);返回了1个exposedObject,就是a的代理对象。

ok,b初始化生命周期执行完毕,又回到了a的初始化生命周期。

a对象对应的BeanWrapper如下

instanceWrapper = {BeanWrapperImpl@1864} "org.springframework.beans.BeanWrapperImpl: 
wrapping object [circle.A@6f204a1a]"

可以看到a的实例是circle.A@6f204a1a

接着执行exposedObject = initializeBean(beanName, exposedObject, mbd);

initializeBean方法中的AbstractAutoProxyCreator#postProcessAfterInitialization不就是我们上一篇文章讲的第二个aop的时机么?那么在initializeBean方法中还会执行代理的逻辑么?如果不会,那么是怎么做到的?

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}

this.earlyProxyReferences中的对象只有1个,就是circle.A@6f204a1a

那么this.earlyProxyReferences.remove(cacheKey)返回了true,说明早期代理引用中的代理对象和当前对象是1个,那也就说明a对象已经被代理过,不需要再代理了。

接着往下看

if (earlySingletonExposure) {
   Object earlySingletonReference = getSingleton(beanName, false);
   if (earlySingletonReference != null) {
      if (exposedObject == bean) {
         exposedObject = earlySingletonReference;
      }
      else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
         String[] dependentBeans = getDependentBeans(beanName);
         Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
         for (String dependentBean : dependentBeans) {
            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
               actualDependentBeans.add(dependentBean);
            }
         }
         if (!actualDependentBeans.isEmpty()) {
            throw new BeanCurrentlyInCreationException();
         }
      }
   }
}

首先从二级缓存拿出来了我们的代理对象引用earlySingletonReference即circle.A@6f204a1a

接着有个判断,判断代理后的a对象和a对象是否指向同一个引用

    if (exposedObject == bean) {
       exposedObject = earlySingletonReference;
    }

如果是的话,那么执行exposedObject = earlySingletonReference;为什么这么做?

先看下3个对象分别代表的是什么?


bean即a对象是spring通过反射创建的对象。

exposedObject即a对象的暴露对象,是a对象经过了下面2个方法以后的对象。

`populateBean(beanName, mbd, instanceWrapper);`

`exposedObject = initializeBean(beanName, exposedObject, mbd);`

earlySingletonReference是a对象的代理对象,earlySingletonReference持有a对象的引用A@1869。

earlySingletonReference = {$Proxy22@2467} "circle.A@6f204a1a"
 h = {JdkDynamicAopProxy@2598} 
  advised = {ProxyFactory@2627} 
   targetSource = {SingletonTargetSource@2631} 
    target = {A@1869} 

那也就是说如果bean对象和经过populateBean方法以及initializeBean方法以后的exposedObject是1个对象。

还会有不一样的情况吗?当然有,如果你的后置处理器改变了引用呢?比如我在我的后置处理器重新创建1个A对象。

那么会怎么样呢?进入else if分支呗

else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
   String[] dependentBeans = getDependentBeans(beanName);
   Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
   for (String dependentBean : dependentBeans) {
      if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
         actualDependentBeans.add(dependentBean);
      }
   }
   if (!actualDependentBeans.isEmpty()) {
      throw new BeanCurrentlyInCreationException();
   }
}

还好idea自带evaluate expression的功能。我们用这个功能执行一下就知道了

allowRawInjectionDespiteWrappinghasDependentBean(beanName)都为true

getDependentBeans(beanName);返回1个String数组,里面是所有依赖a对象的bean的名称即b。

接下来遍历所有依赖a对象的bean,判断是否已经被创建,如果已经被创建返回的是false。

protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
		if (!this.alreadyCreated.contains(beanName)) {
			removeSingleton(beanName);
			return true;
		}
		else {
			return false;
		}
	}

因为b已经被创建了。所以返回false。

if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean))返回的是true。

使用idea可以执行以下代码。

!removeSingletonIfCreatedForTypeCheckOnly(getDependentBeans("a")[0])

上面的代码逻辑整理一下就是:如果a对象的bean和exposedObject不相同,那么遍历所有依赖a对象的bean的名称。 判断bean是否被创建,如果已经被创建,那就抛出异常。

为什么呢?

因为所有依赖A的实例,并且已经创建对象的bean依赖的是A的早期引用对象即代理对象earlySingletonReference。

但是要返回的对象也就是要放进去一级缓存的对象是exposedObject。

现在是单例模式,所有要依赖于A的bean和一级缓存里的A的bean应当是一个。

所以如果出现了exposedObject和bean不一样的情况,spring最后抛出了异常:

"Bean with name a has been injected into other beans [b] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example."

翻译

作为循环引用的一部分,名为a的Bean在其原始版本中被注入到其他Bean中,但最终被封装。这意味着其它bean使用的不是a的最终版本。这通常是过度渴望类型匹配的结果,例如,考虑在关闭“allowEagleInit”标志的情况下使用“getBeanNameForType”。

最后如果exposedObject == bean 那么 exposedObject = earlySingletonReference;

exposedObject = earlySingletonReference;相当于bean= earlySingletonReference;

此时3者指向的都是同一个对象即代理对象。AbstractAutowireCapableBeanFactory#doCreateBean返回了exposedObject即earlySingletonReference。

最后通过DefaultSingletonBeanRegistry#addSingleton将a从二级缓存移除加入一级缓存。

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}

以一个问题结束吧


为什么需要二级缓存?为什么需要bean的半成品需要提前暴露一个工厂? 

AOP就是一个原因吧!现在有一个实例A,实例B要依赖A,但是A需要被代理,也就是说,A被代理后才能注入给B,那B现在就要注入A,总不能等整个容器所有bean都实例化好后再来注入吧,讲道理也不是不可能,只是spring觉着太麻烦没那个必要,干脆,在注入的时候就直接AOP!