av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁技術(shù)文章
文章詳情頁

spring解決循環(huán)依賴

瀏覽:7日期:2023-08-11 11:21:51

概述

循環(huán)依賴就是依賴關(guān)系形成環(huán),比如最簡單的循環(huán)依賴:A對象依賴B,B對象依賴A

屬性注入與循環(huán)依賴

如果是構(gòu)造器注入,如果循環(huán)依賴對象沒法構(gòu)建,因為還未實例化 如果是屬性注入但是作用域是prototype,spring不會緩存其對象實例,也不能處理循環(huán)依賴的情況 如果是屬性注入singleton的,其bean的實例化過程與屬性注入過程是分開的,并且spring提供了三個map(就是大家說三級緩存)來實現(xiàn)。

spring屬性注入處理循環(huán)依賴的方式

通過以下xml方式配置一個循環(huán)依賴的示例:

<bean class='com.example.leetcode.spring.bean.Person'> <property name='parent' ref='person2'></property> <property name='name' value='tom'></property></bean><bean class='com.example.leetcode.spring.bean.Person'> <property name='parent' ref='person1'></property> <property name='name' value='jack'></property></bean>

spring循環(huán)依賴處理幾個關(guān)鍵位置:

獲取bean對象

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name); Object bean; // 這里會檢查單例bean是否已經(jīng)在注冊表,并返回。 // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) {logger.trace('Returning eagerly cached instance of singleton bean ’' + beanName + '’ that is not fully initialized yet - a consequence of a circular reference'); } else {logger.trace('Returning cached instance of singleton bean ’' + beanName + '’'); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } ...}

DefaultSingletonBeanRegistry(單例對象注冊表)的幾個關(guān)鍵屬性。

// 用來存儲已經(jīng)創(chuàng)建好的單例對象 /** Cache of singleton objects: bean name to bean instance. */ private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 用來存儲單例beanname到ObjectFactory的映射 /** Cache of singleton factories: bean name to ObjectFactory. */ private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 用來提前存儲還未初始化好的單例對象 /** Cache of early singleton objects: bean name to bean instance. */ private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

DefaultSingletonBeanRegistry.getSingleton()的實現(xiàn).

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

AbstractAutowireCapableBeanFactory.doCreateBean創(chuàng)建對象與注入屬性

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { ... instanceWrapper = createBeanInstance(beanName, mbd, args); ... // 檢查是否提前將單例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'); } // 這里將beanname與工廠映射放入緩存注冊表中(也就是上面的singletonFactories) addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } ... // 注入依賴屬性 populateBean(beanName, mbd, instanceWrapper); ...}

假設我們從beanfactory獲取person1對象, 循環(huán)依賴處理流程如下:

1.通過AbstractBeanFactory.doGetBean('persion1')獲取對象

2.因為一開始通過DefaultSingletonBeanRegistry.getSingleton()什么都沒有,進入AbstractAutowireCapableBeanFactory.doCreateBean()進行創(chuàng)建

3.AutowireCapableBeanFactory.doCreateBean()里面執(zhí)行完創(chuàng)建邏輯,因為是singleton將beanname與工廠的映射加入到addSingletonFactory()到緩存

4.開始處理person1對象的屬性依賴populateBean()

5.當發(fā)現(xiàn)person1的parent屬性是一個引用時,通過beanfactory.getBean('person2')獲取依賴對象(org.springframework.beans.factory.support.BeanDefinitionValueResolver#resolveReference)

6.此時進入person2的創(chuàng)建流程, person2也沒有緩存,開始實例化并加入到addSingletonFactory()到緩存

7.person2在通過populateBean()注入屬性依賴發(fā)現(xiàn)依賴person1, 此時通過beanfactory.getBean('person1')獲取依賴對象

8.此時AbstractBeanFactory.doGetBean('persion1')獲取對象執(zhí)行到getSingleton('person1')進行以下判斷:

從singletonObjects.get(beanName)獲取到null 進入if條件,對singletonObjects同步 從earlySingletonObjects.get(beanName);獲取也為null 進入內(nèi)層if,通過singletonFactories.get(beanName);獲取到最開始bean實例化之后的beanname與工廠緩存信息 獲取到僅實例化完成的bean,并earlySingletonObjects.put(beanName, singletonObject); 然后刪除singletonFactories.remove(beanName);

9.此時從getSingleton('person1')返回了一個僅實例化尚未注入的bean引用

10.person2在第7步獲取到person1僅實例化未注入的對象引用。

11.person2完成屬性注入并返回。

12.person2被addSingleton(beanName, singletonObject);中singletonObjects.put(beanName, singletonObject)緩存,并刪除singletonFactories.remove(beanName);earlySingletonObjects.remove(beanName);

13.person1在5步獲取到person2的對象并完成屬性注入

14.person1對象返回(因為一開始person2獲取的是person1的引用,此時person1完成注入是能看到注入后的對象)

15.person1被addSingleton(beanName, singletonObject);中singletonObjects.put(beanName, singletonObject)緩存,并刪除singletonFactories.remove(beanName);earlySingletonObjects.remove(beanName);

16.返回最終的person1對象

關(guān)于三個map(三級緩存)

在出現(xiàn)循環(huán)依賴時,三個map之間的流程如下:

先從singletonFactories獲取工廠,并通過getObject獲取對象并移除緩存,將對象緩存到earlySingletonObjects通過earlySingletonObjects獲取提前曝光的對象對象創(chuàng)建并初始化完成之后,對象信息保留在singletonObjects并移除過earlySingletonObjects中的緩存

earlySingletonObjects二級緩存是雞肋嗎?

earlySingletonObjects緩存的目的是,通過三級緩存在獲取對象會執(zhí)行一些列的后置處理器,通過earlySingletonObjects來緩存提升性能。

以上就是spring解決循環(huán)依賴的詳細內(nèi)容,更多關(guān)于sping 循環(huán)依賴的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 看真人视频一级毛片 | 美女久久久久 | 久久国产一区二区三区 | 最新av在线网址 | 97av视频在线观看 | 中文字幕第一页在线 | 热久久999 | 欧美在线视频一区二区 | av免费入口 | 美女视频黄色的 | 国产欧美久久精品 | 日韩精品免费一区 | 亚洲香蕉 | xx视频在线| 久久91精品 | 日韩乱码一二三 | 久久99精品久久久久久青青日本 | 日本一区视频在线观看 | av中文字幕在线 | 国产午夜视频 | 日韩三级在线观看 | 精品真实国产乱文在线 | www.夜夜骑.com| 国产亚洲精品一区二区三区 | 国产成人在线一区二区 | 日韩一区二区三区视频在线播放 | 最近中文字幕第一页 | 99久久久国产精品 | 99精品视频网 | 黄色亚洲 | 久艹网站 | 国产一区二区三区四区五区加勒比 | 中文字幕在线国产 | 91国自视频 | 国产精品视频一区二区三区 | 国产精品一区二区三 | 久久视频免费看 | 91资源在线| 欧洲精品视频一区 | 在线欧美视频 | 国产精品久久久久久久久污网站 |