Spring 是如何 解決迴圈依賴的問題

2021-09-25 04:30:35 字數 1536 閱讀 5315

初次遇到這個問題是在開發中,但是沒有深究,前一陣參加面試就被問到這個問題,當時真是非常後悔,怎麼沒有好好研究一下呢。現在來亡羊補牢吧。

迴圈依賴的定義:

迴圈依賴就是迴圈引用,就是兩個或多個bean 相互之間的持有對方,比如circlea 引用circleb , circleb 引用circlec, circlec 引用circlea ,則它們最終反映為乙個環。

1 .構造器迴圈依賴

表示通過構造器注入構成的迴圈依賴, 此依賴是無法解決的,只能丟擲beancurrentlylncreationexception異常表示迴圈依賴。

如在建立testa 類時, 構造器需要testb 類,那將去建立testb , 在建立testb 類時又發現需要testc 類, 則又去建立testc , 最終在建立testc 時發現又需要testa ,從而形成乙個環,沒辦法建立。

spring 容器將每乙個正在建立的bean 識別符號放在乙個「當前建立bean 池」中, bean 識別符號:在建立過程中將一直保持在這個池中,因此如果在建立bean 過程中發現自己已經在「當前建立bean 池」 裡時,將丟擲beancurrentlylncreationexception 異常表示迴圈依賴;而對於建立完畢的bean 將從「 當前建立bean 池」中清除掉。

2. setter 迴圈依賴

表示通過setter 注入方式構成的迴圈依賴。對於setter 注入造成的依賴是通過spring 容器提前暴露剛完成構造器注入但未完成其他步驟(如setter 注入)的bean 來完成的,而且只能解決單例作用域的bean 迴圈依賴。通過提前暴露乙個單例工廠方法,從而使其他bean 能引用到該bean 

具體步驟如下。

l. spring 容器建立單例「testa 」 bean ,首先根據元參構造器建立bean ,並暴露乙個「0bjectfactory」用於返回乙個提前暴露乙個建立中的bean ,並將「testa」識別符號放到「當前建立bean 池」, 然後進行setter 注入「testb 」 。

2. spring 容器建立單例「 testb 」 bean ,首先根據無參構造器建立bean ,並暴露乙個「 objectfactory」用於返回乙個提前暴露乙個建立中的bean ,並將「testb」識別符號放到「當前建立bean 池」,然後進行setter 注入「circle 」 。

3. spring 容器建立單例「 testc 」 bean ,首先根據元參構造器建立bean ,並暴露乙個「 objectfactory」用於返回乙個提前暴露乙個建立中的bean ,並將「testc」識別符號放到「當前建立bean 池」,然後進行setter 注入「testa」 。進行注入「testa」時由於提前暴露了「objectfactory」工廠,從而使用它返回提前暴露乙個建立中的bean 。

4. 最後在依賴注入「testb 」和「testa 」,完成setter 注入。

3.prototype 範圍的依賴處理

對於「prototype」作用域bean, spring 容器無法完成依賴注入,因為spring 容器不進行快取「prototype」作用域的bean ,因此無法提前暴露乙個建立中的bean.

參考:《spring 原始碼深度解析》(第二版)

Spring如何解決迴圈依賴

比如 在a類引入b物件,在b類引入a物件,建立a的時候需要依賴b,建立b的時候需要依賴a,而各自建立物件的時候,其互相依賴的物件還沒有建立完成,就導致各自都無法成功建立物件。這就是迴圈依賴。class aclass b解決迴圈依賴的方法很簡單,如下所示,先例項化a和b,此時都沒初始化,即都沒有對各自...

spring如何解決迴圈依賴

1.構造器注入 無法解決 構造器注入時,a,b都沒有進行初始化物件 構造方法無法執行完成 2.spring 為了解決單例的迴圈依賴問題,使用了 快取。其中一級快取為單例池 singletonobjects 二級快取為提前 物件 earlysingletonobjects 快取為提前 物件工廠 sin...

Spring如何解決迴圈依賴

多個bean之間相互依賴,形成了乙個閉環。比如 a依賴於b b依賴於c c依賴於a 通常來說,如果問spring容器內部如何解決迴圈依賴,一定是指預設的單例bean中,屬性互相引用的場景。也就是說,spring的迴圈依賴,是spring容器注入時候出現的問題。例項化a 將半成品的a放入singlet...