最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Spring如何解決循環(huán)引用的問題

 更新時間:2023年08月13日 09:19:39   作者:隨機的未知  
在Spring框架中,當兩個或多個Bean之間存在相互依賴關系時,可能會導致循環(huán)引用的問題,循環(huán)引用指的是兩個或多個Bean之間互相依賴,形成一個循環(huán)鏈,本文將和大家一起探討Spring如何解決循環(huán)引用的問題,感興趣的小伙伴跟著小編一起來看看吧

Spring如何解決循環(huán)引用的問題

關于循環(huán)引用,首先說一個結論:

Spring能夠解決的情況為:兩個對象都是單實例、且通過set方法進行注入。

兩個對象都是單實例,通過構造方法進行注入,Spring不能進行循環(huán)引用問題;

兩個對象都是多實例的情況下,不管是set注入,還是構造注入,都不能解決Spring循環(huán)引用問題。

循環(huán)引用問題介紹

循環(huán)引用問題即:

有A,B兩個類,A類中有B類型的成員變量b、B類中有A類型的成員變量a。創(chuàng)建a的過程需要b,創(chuàng)建b的過程又需要a;

循環(huán)引用問題演示

循環(huán)引用問題分析

請看如下流程:

  1. 調用getBean("a")來獲取a對象;
  2. 先調用getSingleton("a")來嘗試獲取a,但是獲取不到;
  3. 需要調用doCreateBean()來創(chuàng)建a;
  4. a的b屬性是null,需要填充b屬性;
  5. 調用getBean("b")來獲取b對象;
  6. 先調用getSingleton("b")來嘗試獲取b,但是獲取不到;
  7. 需要調用doCreateBean()來創(chuàng)建b;
  8. b的a屬性是null,需要填充a屬性;
  9. 又需要要調用getBean("a")來獲取a。

這時getBean("a")可以獲取到嗎?如果能獲取到,是在哪里獲取的?如果獲取不到,又會有什么問題呢?

我們首先看下getSingleton()源碼:

image-20230809203549677

addSingleton方法如下圖:

addSingleton

如此可以看到,在進行實例化、屬性填充、初始化都完成后才會放到singletonObjects中。

那getSingleton()方法就獲取不到a,只能再去創(chuàng)建a對象了嗎?當然不是,如果再去創(chuàng)建a,a就不是單例的呢。

所以這就需要**沒有創(chuàng)建完全的a也要存儲起來。**但是并沒有存儲到singletonObjects中,因為singletonObjects是存儲例化、屬性填充、初始化都完成后的對象。

Spring又為我們定義了兩個存儲的位置:earlySingletonObjects、singletonFactories。

那什么時候將未創(chuàng)建完全的對象存儲起來呢?

這我們應該在實例化對象完成后,填充屬性前的代碼查找。可以看到如下代碼:

doCreateBean

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
addSingletonFactory方法源碼如下:
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);
        }
    }
}

實例化后,會把創(chuàng)建非完全體對象的工廠放到singletonFactories里,這個工廠就是lambda表達式() -> getEarlyBeanReference(beanName, mbd, bean)調用的getEarlyBeanReference(beanName, mbd, bean)方法。

getEarlyBeanReference

addSingletonFactory還會把earlySingletonObjects、registeredSingletons中的對象刪除。

singletonFactories 存儲:不完全體的bean的id作為key,一個工廠作為value; 工廠方法是lambda表達式()->getEarlyBeanReference(beanName, mbd, bean) 此方法內部使用了BeanPostProcessor。

singletonFactories為什么不存儲未完全體的a,而存儲一個工廠方法呢?

這意味著他會處理一些復雜功能。

最簡單的循環(huán)引用的問題

上述介紹的循環(huán)引用的問題,是最簡單的情況。還有一些復雜情況。

如果A需要做AOP,需要為A做代理呢?或者B也要做代理呢?

復雜情況的循環(huán)引用

代理是在初始化階段使用BeanPostProcessor的postProcessAfterInitialization()方法來做的。

singletonFactories存工廠的原因

singletonFactories存工廠的原因:

為b填充屬性a時,需要獲取到不完全體的a,為b賦值; 并且如果A需要做代理; 而代理是在BeanPostProcessor中的postProcessAfterInitialization()方法做的; 所以singletonFactories存儲的是一個工廠(里面的方法是用BeanPostProcessor中的); 這樣就無需在a初始化的過程中創(chuàng)建代理了,可以把a的代理提前創(chuàng)建出來。

那在A創(chuàng)建過程中是否還要創(chuàng)建代理呢?————不會。

在上面提前創(chuàng)建a的代理完成后,會將代理對象放到代理緩存中,在a初始化創(chuàng)建代理時,直接從代理緩存中拿就可以了。

站在b的角度講,現(xiàn)在b的屬性填充完成了,后面就是初始化了,在初始化過程中,就可以走正常的代理過程了。

a在填充屬性時,就可以填充b的代理了,就可以走初始化了,初始化過程中的代理從代理緩存獲取就可以了。

為b填充a代理對象分析

doGetBean()中的getSingleton方法:

getSingleton

getSingleton重載1

getSingleton重載2

在為b填充a的代理時,singletonFactory.getObject()就會回調存儲起來的那個lambda表達式()->getEarlyBeanReference(beanName, mbd, bean)。

核心代碼

會把a的代理獲取出來;

然后把a的代理放到earlySingletonObjects中;

把存儲的a工廠的lambda表達式從singletonFactories中移除。

b初始化完成后,b就是完全體了,調用addSingleton()方法就會把b存儲到singletonObjects中了。

等a再初始化完成就是完全體了。

這樣就解決了循環(huán)引用問題。

以上就是詳解Spring如何解決循環(huán)引用的問題的詳細內容,更多關于Spring循環(huán)引用的資料請關注腳本之家其它相關文章!

相關文章

  • Springboot項目構建時各種依賴詳細介紹與依賴關系說明詳解

    Springboot項目構建時各種依賴詳細介紹與依賴關系說明詳解

    SpringBoot通過spring-boot-dependencies統(tǒng)一依賴版本管理,spring-boot-starter-web簡化Web開發(fā)流程,自動配置核心功能,提升開發(fā)效率與兼容性,下面通過本文介紹Springboot項目構建時各種依賴詳細介紹與依賴關系說明,感興趣的朋友一起看看吧
    2025-08-08
  • Java中的ConcurrentLinkedQueue使用解析

    Java中的ConcurrentLinkedQueue使用解析

    這篇文章主要介紹了Java中的ConcurrentLinkedQueue使用解析,一個基于鏈接節(jié)點的無界線程安全隊列,此隊列按照 FIFO(先進先出)原則對元素進行排序,隊列的頭部是隊列中時間最長的元素,需要的朋友可以參考下
    2023-12-12
  • Java集成Onlyoffice的示例代碼及場景分析

    Java集成Onlyoffice的示例代碼及場景分析

    這篇文章主要介紹了Java集成Onlyoffice的示例代碼及場景分析,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2025-05-05
  • Java中IO流文件讀取、寫入和復制的實例

    Java中IO流文件讀取、寫入和復制的實例

    下面小編就為大家?guī)硪黄狫ava中IO流文件讀取、寫入和復制的實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • Spring使用@Autowired為抽象父類注入依賴代碼實例

    Spring使用@Autowired為抽象父類注入依賴代碼實例

    這篇文章主要介紹了Spring使用@Autowired為抽象父類注入依賴代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Java實戰(zhàn)員工績效管理系統(tǒng)的實現(xiàn)流程

    Java實戰(zhàn)員工績效管理系統(tǒng)的實現(xiàn)流程

    只學書上的理論是遠遠不夠的,只有在實戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+Mysql+Maven+HTML實現(xiàn)一個員工績效管理系統(tǒng),大家可以在過程中查缺補漏,提升水平
    2022-01-01
  • springmvc分層領域模型概念詳解

    springmvc分層領域模型概念詳解

    本文核心為分層領域模型(VO , PO , BO, DAO ,POJO等)概念的個人理解,結合springmvc淺談分層領域模型的相關知識,感興趣的朋友跟隨小編一起看看吧
    2021-08-08
  • Java中超過1000萬數(shù)據就自動轉為科學計數(shù)法的原因分析與解決方案

    Java中超過1000萬數(shù)據就自動轉為科學計數(shù)法的原因分析與解決方案

    在 Java 開發(fā)中,你是否遇到過這樣的場景:當數(shù)值達到 1000 萬(10^7)時,原本期望的整數(shù)格式突然變成了1.0E7這樣的科學計數(shù)法?本文將深入分析背后的原因,并提供 3 種實用解決方案,幫你徹底解決這個問題,需要的朋友可以參考下
    2026-03-03
  • 使用Logback設置property參數(shù)方式

    使用Logback設置property參數(shù)方式

    這篇文章主要介紹了使用Logback設置property參數(shù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • java 中JDBC連接數(shù)據庫代碼和步驟詳解及實例代碼

    java 中JDBC連接數(shù)據庫代碼和步驟詳解及實例代碼

    這篇文章主要介紹了java 中JDBC連接數(shù)據庫代碼和步驟詳解及實例代碼的相關資料,需要的朋友可以參考下
    2017-02-02

最新評論

理塘县| 潼关县| 兴宁市| 留坝县| 得荣县| 黄陵县| 玛纳斯县| 陇南市| 瓦房店市| 阜阳市| 娱乐| 鸡西市| 平罗县| 红桥区| 兴隆县| 琼海市| 伊川县| 新野县| 富裕县| 新兴县| 长宁区| 新泰市| 曲阳县| 朝阳市| 连江县| 绥宁县| 松滋市| 双流县| 巴林右旗| 明水县| 南昌县| 垫江县| 绥江县| 云龙县| 府谷县| 永清县| 台南市| 岳阳县| 巴彦淖尔市| 卢氏县| 黑山县|