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

Spring 中的循環(huán)引用問題解決方法

 更新時間:2025年04月27日 11:11:21   作者:我可是ikun啊  
這篇文章主要介紹了Spring 中的循環(huán)引用問題解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友參考下吧

本章來聊聊Spring 中的循環(huán)引用問題該如何解決。這里聊的很粗糙,并沒有那么細節(jié),只是大概了解了一點。

什么是循環(huán)引用?

如下圖所示:

圖中有兩個類,一個 Class A ,A 中又引用了 B,Class B 中又引用了 A 。(基于 setter 注入和字段注入)

當 Spring 容器想要創(chuàng)建 A 時發(fā)現(xiàn) A 中需要使用到 B 對象,此時就去創(chuàng)建 B ,在創(chuàng)建 B 對象時又發(fā)現(xiàn)還需要引用 A ,此時就發(fā)生循環(huán)引用了。

當然循環(huán)引用并非就是 A 引用 B ,B 引用 A 的情況,還有很多,如:

當然,此圖比較草率。

有了循環(huán)依賴就會有死循環(huán)的問題。

循環(huán)依賴

來看看死循環(huán)產(chǎn)生的過程:

為什么這里是半成品呢?要是熟悉 Spring-bean 的 生命周期就會知道,首先會去調用的是構造函數(shù),像一些依賴注入啊,還有一些接口的實現(xiàn)的方法重寫啊還有后置處理器初始化方法,想這些都還沒有去執(zhí)行,所以說他還是一個半成品對象。

繼續(xù)向后執(zhí)行:

此時,在容器中找不到 A 對象啊,那么他又去實例化 A 了。此時死循環(huán)就產(chǎn)生了,這個就叫做 循環(huán)依賴。

三級緩存:

緩存級別源碼名稱作用
一級緩存singletonObjects存儲已經(jīng)完全初始化好的單例 Bean。當 Bean 初始化完成,所有依賴項都已注入,就會放入此緩存,供后續(xù)獲取 Bean 時直接使用,提高獲取單例 Bean 的效率。
簡單來說:單例池,緩存已經(jīng)經(jīng)歷了完整的生命周期,已經(jīng)初始化完成了的對象。
二級緩存
earlySingletonObjects

存儲提前暴露的原始 Bean,即已經(jīng)開始實例化但還未完成初始化(如未填充屬性)的 Bean。用于解決在構造器注入過程中發(fā)生的循環(huán)依賴問題,確保在循環(huán)依賴情況下 Bean 只被創(chuàng)建一次,也能解決多線程并發(fā)下獲取不完整 Bean 的性能問題。

簡單來說:緩存早期的 bean 對象(生命周期未完成)

三級緩存singletonFactories

存儲 Bean 的 ObjectFactory,用于生成原始 Bean 的代理對象。當遇到循環(huán)依賴且涉及到代理對象創(chuàng)建時,Spring 會將 ObjectFactory 放入三級緩存,在后續(xù)需要時通過它來獲取 Bean 的實例,以處理代理相關情況,統(tǒng)一處理普通 Bean 和代理 Bean。

簡單來說:緩存 objectFactory,表示對象工廠,用來創(chuàng)建某個對象

我們一個個來說

三級緩存解決循環(huán)依賴

回到上個圖片:

按照一級緩存的邏輯,走完一個生命周期才能將對象存儲在緩存中?。ㄈ前氤善罚?,那么這個流程中必然是沒有對象存在緩存中的。

走到這里發(fā)現(xiàn)了,單憑一級緩存是沒有辦法解決循環(huán)依賴的。

要想打破這個循環(huán)依賴,需要一個中間人的參與(暫時存放一個半成品的 對象),這個中間人就是二級緩存。

二級緩存

我們重新走一遍流程:

實例化一個 A 對象,此時生成一個 原始對象 A(半成品的 A )只是開辟了空間,執(zhí)行了一個構造方法
就將這個方法存入這個二級緩存中
發(fā)現(xiàn)創(chuàng)建 A 對象需要依賴 B 對象,就注入 B,B 又不存在,那么就實例化一個 B
B還是和之前的 A 一樣,同時也將 原始對象存入這個 二級緩存中
但是在 B 中注入 A 時,發(fā)現(xiàn)了緩存中有一個原始對象 A ,那么就可以打破循環(huán)依賴,使 B創(chuàng)建成功 
此時 B 已經(jīng)創(chuàng)建成功了,就可以存儲到 一級緩存中了,那么也就可以將 B 注入進 A 了
A 也就可以創(chuàng)建成功,成功之后也需要存入一級緩存(此時二級緩存中的半成品對象也可以清理掉了)

此時似乎使用 二級緩存 + 一級緩存 就可以解決循環(huán)依賴的問題了啊,那還要三級緩存干嘛呢?

我們假設,如果這個 A 是個代理對象呢?

兩個原因:

代理對象創(chuàng)建時機的問題:Spring 的代理對象通常是在 Bean 初始化過程的特定階段創(chuàng)建的(例如在初始化方法執(zhí)行之后)。在處理循環(huán)依賴時,如果僅使用一級和二級緩存,當一個 Bean 在創(chuàng)建過程中需要依賴另一個 Bean,而另一個 Bean 又依賴這個 Bean 時,由于代理對象還未創(chuàng)建,二級緩存中存儲的只是原始的 Bean 實例,不是代理對象。如果將原始 Bean 實例注入到依賴它的 Bean 中,就會導致依賴方持有的是原始 Bean 而不是代理 Bean,這不符合 Spring 的設計要求。
保證代理對象的一致性:對于同一個 Bean,無論從何處獲取,都應該保證是同一個代理對象。如果沒有三級緩存,在循環(huán)依賴場景下可能會出現(xiàn)多次創(chuàng)建代理對象的情況,從而破壞了單例 Bean 的唯一性和代理對象的一致性。

三級緩存

此時我們使用 三級緩存來代替二級緩存

一級緩存+二級緩存 不是不能解決 代理對象的問題嗎,那么這里就使用三級緩存來做,再注入 A 時,通過對象工廠生成,你是代理對象那就生成一個代理對象再注入,你是一個普通對象就生成一個普通對象 再注入。

雖然說 通過 A 的 ObjectFactory 對象創(chuàng)建了一個代理對象,但是此時還是一個半成品對象,這里就需要 二級緩存 來存放了。此時存放的是一個 A 的代理對象(半成品)。在完成的對象存放在一級緩存中后被刪除了。

到這里借助了三級緩存,解決了大部分循環(huán)依賴的問題;借助工廠類,幫助我們生成工廠對象來產(chǎn)生代理對象。

為什么是大部分的循環(huán)依賴呢,因為某些循環(huán)引用 spring 框架解決不了,需要手動來解決。例如:構造方法注入產(chǎn)生的循環(huán)依賴。

class A {
    private B b;
    public A(B b) {
        this.b = b;
    }
}
class B {
    private A a;
    public B(A a) {
        this.a = a;
    }
}

三級緩存可以解決初始化過程中的循環(huán)依賴,卻無法解決構造函數(shù)產(chǎn)生的循環(huán)依賴,那么該怎么辦解決呢?

我們只需要在 參數(shù)之前加上一個 @Lazy (延遲加載)

public A(@Lazy B b) {
        System.out.println("A的構造方法");
        this.b = b;
    }

延遲加載的意思就是什么時候需要對象再進行對象的創(chuàng)建,而不再是直接把對象注入進來。

到此就解決循環(huán)依賴了。

三級緩存 + 一級緩存 存在的問題

再回顧三級緩存中,既然三級緩存代替了二級緩存,那么能否使用通過 一級緩存 + 三級緩存來解決循環(huán)依賴呢?

沒有二級緩存的后果:

如果沒有二級緩存,當出現(xiàn)循環(huán)依賴時,雖然三級緩存可以提供早期引用,但無法區(qū)分同一個 Bean 的不同狀態(tài)。例如,無法區(qū)分是正在創(chuàng)建的 Bean 還是已經(jīng)創(chuàng)建好但還未注入屬性的 Bean,可能會導致錯誤的 Bean 引用被使用,進而引發(fā)循環(huán)依賴問題無法正確解決。

每次需要使用工廠生成好的對象直接去二級緩存拿出來就可以了,不用再次去生成這個對象。這也是二級緩存的核心作用之一。

如果沒有二級緩存,那么就有可能產(chǎn)生多例的情況,此時處理起來就更麻煩了。

到此這篇關于Spring 中的循環(huán)引用問題的文章就介紹到這了,更多相關Spring 循環(huán)引用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

曲周县| 鞍山市| 合川市| 潢川县| 上栗县| 锡林浩特市| 涟源市| 凤庆县| 锡林浩特市| 尼木县| 额尔古纳市| 宜州市| 金川县| 雷山县| 白水县| 广灵县| 乳山市| 乐都县| 成安县| 英德市| 四平市| 台北县| 龙门县| 河南省| 磐石市| 木里| 浠水县| 文安县| 上林县| 阳原县| 北海市| 宁河县| 桑植县| 原平市| 五河县| 长岭县| 塔城市| 永定县| 西安市| 诏安县| 昭觉县|