doCreateBean创建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"); } //为了避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); }
//aop在这里将advice动态织入bean中,如没有则直接返回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; }
一、earlySingletonExposure是提早曝光单例,曝光单例的条件如下
1、mbd.isSingleton()
2、this.allowCircularReferences
是否允许循环依赖
3、isSingletonCurrentlyInCreation
在Spring中会有专门属性默认为DefaultSingletonBeanRegistry类的this.singletonsCurrentlyInCreation属性来记录bean的加载状态,在bean开始创建前会将beanName加入到该属性中,在bean创建结束后会将beanName从属性中移除。
以之前分析的public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)函数里会执行beforeSingletonCreation(beanName)和afterSingletonCreation(beanName);
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "Bean name must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction " + "(Do not request a bean from a BeanFactory in a destroy method implementation!)"); } if (logger.isDebugEnabled()) { logger.debug("Creating shared instance of singleton bean '" + beanName + "'"); } beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { // Has the singleton object implicitly appeared in the meantime -> // if yes, proceed with it since the exception indicates that state. singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } afterSingletonCreation(beanName); } if (newSingleton) { addSingleton(beanName, singletonObject); } } return singletonObject; } }
当上述的三个条件都满足时,会执行addSingletonFactory。
二、加入SingletonFactory原理
假设A类有属性B,B类有属性A,那么初始化A的过程如下图
通过上图可以看出,在实例化B的populate方法中又会再次初始化A,此时调用getBean(A),这个函数不是直接实例化A,而是先去检测缓存中是否已经创建好对应的bean,或者已经创建好对应的ObjectFactory。
Spring处理循环依赖的解决方法,在B中创建依赖A时通过ObjectFactory提供的实例化方法来中断A中属性的填充,使B中持有的A仅仅是刚初始化并没有填充任务属性的A,而这正初始化A的步骤还是在最开始创建A的时候进行,但是因为A与B中A所表示的属性地址是一样的,所以A中创建好的属性填充自然可以通过B中的A获取。