spring循环引用源码(是如何解决循环引用的)

创建对象的三级缓存介绍。

一、一级缓存singletonFactories

如果是单例对象且可以提前暴露引用,则放入singletonFactories缓存中。

// 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"); } //ObjectFactory放入一级缓存中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); }

getEarlyBeanReference因为会调用SmartInstantiationAwareBeanPostProcessor,可能会提前生成代理对象。

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; }

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(singletonFactory, "Singleton factory must not be null"); synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { this.singletonFactories.put(beanName, singletonFactory); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }

二、二级缓存earlySingletonObjects

如果B依赖A,A又依赖B,则在A创建的时候,会触发B对象的二级缓存创建。

在A依赖注入的时候,会触发doGetBean(B)

protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = transformedBeanName(name); Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } //省略代码 return bean; }

然后触发getSingleton(B), 我们看到singletonFactory.getObject()被调用,其实就是调用的getEarlyBeanReference方法,而且对象被放到了earlySingletonObjects缓存中,singletonFactories中的缓存被清除。

ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); }

三、三级缓存singletonObjects

当对象完全构建好之后,放入到三级缓存中。

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

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); } }

四、总结

只有单例对象可以放入到一级缓存singletonFactories中,存在循环依赖的时候,一级缓存清掉,得到的对象(可能提前生成代理对象)放入二级缓存earlySingletonObjects中。最终生成的完整对象放入三级缓存singletonObjects中,同时清除一级、二级缓存。

spring循环引用源码(是如何解决循环引用的)(1)

Spring 默认可以解决大部分循环依赖,但是还有一些场景无法解决,你遇到过吗,是什么原因?又是怎么解决的?我们后面再聊。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页