tft每日頭條

 > 圖文

 > spring循環引用源碼

spring循環引用源碼

圖文 更新时间:2024-09-11 11:38:12

創建對象的三級緩存介紹。

一、一級緩存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 默認可以解決大部分循環依賴,但是還有一些場景無法解決,你遇到過嗎,是什麼原因?又是怎麼解決的?我們後面再聊。

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关圖文资讯推荐

热门圖文资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved