在上一节Spring源码解析(四)中,有一些代码并没有仔细分析。而这些代码都和spring解决循环依赖相关的。比较重要的有两处
第一处在 AbstractAutowireCapableBeanFactory的 doCreateBean方法
if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); mbd.resolvedTargetType = beanType; // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { 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 resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } // Initialize the bean instance. Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { exposedObject = initializeBean(beanName, exposedObject, mbd); } }
注意在 createBeanInstance首先实例化一个对象之后,和对这个对象属性值进行填充之前,spring做了一件事。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); }
把这个空的对象先暴露到一个缓存中,这里就涉及到一个概念,spring的三级缓存。接下来就通过三级缓存和 循环依赖的概念说明下spring是怎么解决循环依赖的。
1 解决循环依赖的原理
Spring循环依赖的理论依据其实是Java基于引用传递,当我们获取到对象的引用时,对象的field或者或属性是可以延后设置的。
Spring单例对象的初始化其实可以分为三步:
- createBeanInstance, 实例化,实际上就是调用对应的构造方法构造对象,此时只是调用了构造方法,spring xml中指定的property并没有进行populate
- populateBean,填充属性,这步对spring xml中指定的property进行populate。@Autowired,@Resource 自动注入都在这里执行的。
- initializeBean,调用spring xml中指定的init方法,或者AfterPropertiesSet方法。
会发生循环依赖的步骤集中在第一步和第二步。
2 三级缓存
“三级缓存”主要是指 DefaultSingletonBeanRegistry 中的三个缓存
一级 singletonObjects, 二级 earlySingletonObjects ,三级 singletonFactories
/** Cache of singleton objects: bean name --> bean instance */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256); /** Cache of singleton factories: bean name --> ObjectFactory */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16); /** Cache of early singleton objects: bean name --> bean instance */ private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
singletonObjects指单例对象的cache,singletonFactories指单例对象工厂的cache,earlySingletonObjects指提前曝光的单例对象的cache。
3 解决过程源码
在Spring源码解析(四) 中,分析过了Bean创建的过程,首先Spring会尝试从缓存中获取,这个缓存就是指singletonObjects,主要调用的方法是:
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) { ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return (singletonObject != NULL_OBJECT ? singletonObject : null);}
首先注意两个对象
1 isSingletonCurrentlyInCreation 判断是否当前bean正在创建
2 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); ObjectFactory又可以成为三级缓存
判断是否正在创建的逻辑也是在 DefaultSingletonBeanRegistry这个类里,可以说这个类包办了解决循环依赖的全部功能。
public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.contains(beanName); }
/** Names of beans that are currently in creation */
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(16));
我们再看看这两个变量是什么时候被赋值的。
其实这两个变量是在同一个方法里被赋值的,在AbstractBeanFactory的doGetBean方法中,如果一个bean是第一次被创建,那么就会执行到
if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { 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); }
我们继续看
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "'beanName' 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<Exception>(); } 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);//此时该bean所有的步骤都走完了,包括成员变量的填充,所以就没必要再要二级和三级缓存了,只需要保留一级缓存 } } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
beforeSingletonCreation就是会把这个beanName加入到 singletonsCurrentlyInCreation 这个set中,而 afterSingletonCreation 会从singletonsCurrentlyInCreation 中删除这个beanName。
我们继续看 getSingleton会执行 singletonFactory.getObject();而这个逻辑是在
new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); }
所以继续分析AbstractAutowireCapableBeanFactory的 createBean,在createBean中真正干活的是 doCreateBean。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { instanceWrapper = createBeanInstance(beanName, mbd, args); } final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null); Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null); mbd.resolvedTargetType = beanType; // Allow post-processors to modify the merged bean definition. synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { 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 resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); }
经过createBeanInstance的调用后,bean已经被创建出来了,只是属性值还未填充,也就是说他还只是一个空对象。
然后会执行
addSingletonFactory(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } });
就在这里设置了三级缓存this.singletonFactories.put(beanName, singletonFactory);
此处就是解决循环依赖的关键,这段代码发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来的。这个对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用。
最后再看下三级缓存在哪里被使用的,如果三级缓存里有这个bean那么就不用再创建了,直接拿到这个bean
@SuppressWarnings("unchecked") protected <T> T doGetBean( final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); }
4 为什么是三级缓存
为什么采用三级缓存呢,以下是我个人的理解。首先这三个缓存的作用不同。
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256); private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16); private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
singletonFactories 的value部分存的是ObjectFactory,只有在调用getSingletion时,会执行ObjectFactory的getObject方法,并存入earlySingletonObjects。
注意一下 singletonObjects 和 earlySingletonObjects初始大小的不同。
earlySingletonObjects在一个bean完全完成了初始化后就会清理,所以没必要有太大的容量。
而 singletonObjects经过我的观察后,只有在spring容器 AbstractApplicationContext 调用 close后才会进行清理,也就是说在spring容器的生命周期里他是一直存在的。
因此总结下,singletonFactories只会被执行一次,执行过后 实例化的bean 存入 earlySingletonObjects,并清理singletonFactories。
earlySingletonObjects在创建bean过程中,getSingleton中会被调用,如果一个bean已经存在在 earlySingletonObjects,则不会继续走创建bean流程。并且在bean初始化完成后被清理。
生命周期比ObjectFactory能长一点。
singletonObjects 生命周期是最长的,因此它才是一级缓存。
earlySingletonObjects经过观察它的生命周期是一个bean第一次被调用getSinfleton之后,三级缓存就会清除,放入二级缓存,这是它的开始。它的结束是该bean完全初始化完毕。
所以,一种可能的场景就是A 包括了B,C,B和C都依赖A。A初始化的时候,会将自己先暴露到三级缓存。这样B在初始化自己的时候,发现要依赖A,此时第一次调用三级缓存,同时A从三级缓存
就到了二级缓存。A又发现自己需要依赖C,就初始化C,然后C发现自己依赖A,此时就会调用getSingleton,这个是就是从二级缓存拿的。如果A所有属性都填充好了,就会销毁二级缓存,只保留一级缓存。
5 为什么构造方法的循环依赖无法解决
有之前的只是铺垫,这个问题理解起来就容易多了。ClassA初始化时,在实例化之前会把bean name放到Set<String> singletonsCurrentlyInCreation 。然后当执行ClassA的构造函数时,发现要依赖ClassB。在实例化ClassB时,又需要实例化ClassA,结果发现A的bean并不在缓存里,但是还在singletonsCurrentlyInCreation 里。这就发生了bean同时创建的异常。