源码分析:Spring如何解决单例Bean的循环依赖?

假设Bean为A,第一次对A进行依赖查找时是查不到beanName对应实例的,因为
● singletonObjects:不存在A对应元素,A完全初始化之后才会放进去。
● singletonsCurrentlyInCreation:也不存在A对应元素!用以标识创建中的状态!
看下getSingleton(String beanName,boolean allowEarlyReference);

/**
 * Return the (raw) singleton object registered under the given name.
 * 

Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { //返回提前暴漏的Bean。之所以能解决循环依赖,就是其他Bean依赖当前BeanA的时候singletonFactories返回了A的beanName关联的Objectfactory,而这个ObjectFactory可以提前暴漏未完全初始化的Bean A实例,其实是一个BeanWrapper对象,尚未填充属性和初始化Bean。 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }

所以shareInstance返回null,忽略一些无关代码,于是执行到getSingleton(String,ObjectFactory)代码.

//AbstractBeanFactory.java
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
     
     ....
      Object sharedInstance = getSingleton(beanName, true);
      .....
      // Create bean instance.
        if (mbd.isSingleton()) {
     
           sharedInstance = getSingleton(beanName, () -> {
     
            try {
     
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
     
                // Explicitly remove instance from singleton cache: It might have been put there
                 // eagerly by the creation process, to allow for circular reference resolution.
                 // Also remove any beans that received a temporary reference to the bean.
                 destroySingleton(beanName);
                 throw ex;
              }
           });
           bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }
        .....
        return bean;
}

通过代码细节看到singleObjects中找不到beanName对应的实例,但是后边会根据singletonFactory.getObject()来查找Bean。singletonFactory就是传进来的包含createBean的lambda表达式。但在创建之前需要做一些前置准备,也就是执行beforeSingletonCreation(String beanName);此方法中执行的操作就是“标志A这个Bean在创建中”。即singletonsCurrentlyInCreation.add(String BeanName)方法。

protected void beforeSingletonCreation(String beanName) {
     
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
     
        throw new BeanCurrentlyInCreationException(beanName);
   }
}

//DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
     
    ....
    synchronized (this.singletonObjects) {
     
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
     
            ...
            //this.singletonsCurrentlyInCreation.add(beanName)
            beforeSingletonCreation(beanName);
            ...
            try {
     
                //AbstractAutowireCapableBeanFactory#createBean
               singletonObject = singletonFactory.getObject();
               newSingleton = true;
            }catch(...){
     }
            finally{
     
                ...
                //this.singletonsCurrentlyInCreation.remove(beanName)
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
       
               // 实际执行的是
               // 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);
               //       }
                // }             
               addSingleton(beanName, singletonObject);
            }     
        }
        return singletonObject;
    }

}

创建完Bean以后,即createBean方法执行完毕之后,在finally块中就删除掉Bean A创建中的标识了,即:

afterSingletonCreation(beanName);

实际就是this.singletonsCurrentlyInCreation.remove(beanName);这一行代码起了作用。
Bean A创建完了,但还需要执行下边操作:

 if (newSingleton) {
                  
               addSingleton(beanName, singletonObject);
 }     

这个操作的作用是更新Bean在Spring容器中的缓存状态。

          
   protected void addSingleton(String beanName, Object singletonObject) {
     
           synchronized (this.singletonObjects) {
     
           		//缓存Bean
                this.singletonObjects.put(beanName, singletonObject);
              	//删除beanName关联的用以提前暴漏Bean的ObjectFactory
                 this.singletonFactories.remove(beanName);
                 //删除早期暴漏bean缓存标识
                 this.earlySingletonObjects.remove(beanName);
                 //注册为单例Bean
                 this.registeredSingletons.add(beanName);
             }
  }  

在createBean中执行Bean A实例化的主要就是doCreateBean。
这个方法里判断:

  • 单例Bean
  • 允许循环依赖
  • 正在创建中
    能满足这个三个条件,则Spring会认为这个此时A是需要提前暴漏的单例Bean。因为只有提前暴漏才能解决循环依赖的问题。那么如何提前暴漏单例Bean A呢?
    其实就是给A关联一个ObjectFactory对象。然后再进行Bean的初始化进程即populateBean和initializeBean,最后返回初始化之后的Bean。
    那么代码getSingleton(String beanName, ObjectFactory singletonFactory)中singletonFactory.getObject();这一行就返回了。
    拿到了createBean之后的Bean A实例对象,相当于Bean A已经创建完成了,那么执行finally里的afterSingletonCreation方法。从singletonsCurrentlyInCreation中删除beanName,毕竟Bean已经创建结束了,就是前边已经提到的finally块中的afterSingletonCreation(beanName);这行代码。
    但是本文核心问题来了,如果Bean A依赖了Bean C,那么createBean方法执行时必然会去依赖查找Bean C,而Bean C同样执行getBean方法来实例化和初始化,在这个过程中Bean C如果依赖了Bean A,就形成了A–C—A这样的循环依赖。Bean A虽然还没初始化完成,但是在getBean查找Bean C之前却提前暴漏了自己。也就是 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));这行代码。
//AbstractAutowireCapableBeanFactory
protected Object doCreateBean(
    final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
                                                                throws BeanCreationException {
     
      .........
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    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");
        }
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
     }
    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
     
       populateBean(beanName, mbd, instanceWrapper);
       exposedObject = initializeBean(beanName, exposedObject, mbd);
    }catch(...){
     ...}
    if (earlySingletonExposure) {
     
        Object earlySingletonReference = getSingleton(beanName, false);
        if (earlySingletonReference != null) {
     
            if (exposedObject == bean) {
     
                  exposedObject = earlySingletonReference;
            }
            .........
        }
    }
    return exposedObject;
}

重点看下提前暴漏都做了啥?

 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
/**
 * Add the given singleton factory for building the specified singleton
 * if necessary.
 * 

To be called for eager registration of singletons, e.g. to be able to * resolve circular references. * @param beanName the name of the bean * @param singletonFactory the factory for the singleton object */ protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { //关键代码,beanName关联singletonFactory this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }

给Bean A关联了一个ObjectFactory,也就是getEarlyBeanReference对应的lambda函数对象。放入了singletonFactories中,当Bean C去查BeanA的时候就可以通过getEarlyBeanReference方法获取exposedObject这个早期bean对象。

/**
 * Obtain a reference for early access to the specified bean,
 * typically for the purpose of resolving a circular reference.
 * @param beanName the name of the bean (for error handling purposes)
 * @param mbd the merged bean definition for the bean
 * @param bean the raw bean instance
 * @return the object to expose as bean reference
 */
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;
}

看下Bean C怎么依赖查Bean A?

/**
 * Return the (raw) singleton object registered under the given name.
 * 

Checks already instantiated singletons and also allows for an early * reference to a currently created singleton (resolving a circular reference). * @param beanName the name of the bean to look for * @param allowEarlyReference whether early references should be created or not * @return the registered singleton object, or {@code null} if none found */ @Nullable protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); //如果C来查找A,此时会符合if条件 if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { //这里C来查A一定查不到,符合下边的if条件 singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { //C来查A,singletonFactories是有值的 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { //调用getEarlyBeanReference返回exposedObject singletonObject = singletonFactory.getObject(); //全局也只有此处对earlySingletonObjects进行put this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; }

到这里,基本上已经分析完了关于单例Bean循环依赖的问题,应该还是挺清晰的,总结一下:

Spring通过ObjectFactory提前暴漏一个创建中的Bean(BeanWrapper).给依赖它的Bean使用。让依赖它的Bean的初始化不再需要等待其完全初始化,避免了循环依赖的问题!

你可能感兴趣的:(Spring,Spring,循环依赖)