spring解决循环依赖主要通过三级缓存去完成。
/** 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);在doGetBean中,它首先会通过getSingleton方法去尝试获取bean。
Object sharedInstance = getSingleton(beanName); protected Object getSingleton(String beanName, boolean allowEarlyReference) { /** 首先从singletonObjects获取bean实例 */ Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { /** * 如果singletonObjects还没有此bean,有两种情况 * 1.这个bean正在创建状态,先从earlySingletonObjects获取 * 2.这个bean还没开始创建 */ singletonObject = this.earlySingletonObjects.get(beanName); if (singletonObject == null && allowEarlyReference) { /** * 如果earlySingletonObjects还没有此bean,有两种情况 * 1.说明还未被其他bean注入,正在创建状态,先从singletonFactories获取 * 2.该bean还没开始创建 */ ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); //将此bean放到提前缓存到earlySingletonObjects中 this.earlySingletonObjects.put(beanName, singletonObject); //从singletonObject删除bean this.singletonFactories.remove(beanName); } } } } return singletonObject; }这个方法做了这么一件事,逐步从三级缓存中获取bean:
先到singletonObjects中获取,如果有表示实例化已经完成;否则到earlySingletonObjects获取,如果有表示已经有bean,且存在循环依赖,将此bean作为属性注入了否则到singletonFactories获取,如果存在循环依赖,且此属性是第一次被其他bean作为属性注入相应的在doCreateBean中有这么一串代码:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) throws BeanCreationException { // Instantiate the bean. //BeanWrapper是用来持有创建出来的Bean对象的 BeanWrapper instanceWrapper = null; //如果是Singleton先把缓存中同名的清除 if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } //这是创建Bean的地方由createBeanInstance来完成 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. //这里是对Bean的初始化,依赖注入往往在这里发生, // 这个exposedObject在初始化处理完后会返回作为依赖注入完成后的bean Object exposedObject = bean; try { populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) { 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); } } 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<String>(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 " + "'getBeanNamesOfType' 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; }核心在这里:
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); } }); } 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存放入singletonFactories中 this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }这串代码会在创建bean的时候将自身注册进singletonFactories中。所以可以想象当两个bean互相依赖时,A会将自身注册进singletonFactories中,当它创建B时它可以直接从singletonFactories中获取A的引用所以B能成功创建,当B成功创建后那A也可以从singletonObjects中获取B的引用,最后A也成功创建。
Spring通过三级缓存解决了循环依赖的问题,它会在创建bean的时候将自身注册进一个singletonFactory中,然后创建它的依赖bean时会从这个缓存中获取它的引用使那个依赖bean先进行创造,最后完成自身的依赖。
举个列子:
创建A单例时,放入缓存,然后创建它的依赖B单例。创建B单例时,发现需要依赖注入A单例,然后去加载A单例,此时从缓存中发现A单例正在创建中,于是直接从缓存得到A单例,完成自身的依赖注入。B单例依赖完成后,返回给A单例。A单例再把B单例注入到自身域中完成依赖注入。