先說結論,spring通過**快取機制來解決迴圈依賴問題,構造器依賴除外,即構造器注入可能會報錯。
迴圈依賴的情況如下:
首先spring初始化bean的步驟如下:
這裡只需要簡單的理解為三步:
例項化填充屬性(注入依賴)
初始化完成
spring在建立bean a的時候會先去一級快取(singletonobjects),如果一級快取沒有則再從二級快取(earlysingletonobjects)中獲取,如果二級快取也沒有,則再從**快取(singletonfactories)中獲取,如果還獲取不到,則例項化乙個a,然後放入**快取,然後填充屬性,此刻發現依賴b,於是建立b,同樣的經過上述步驟,由於每級快取都獲取不到,於是例項化b,然後填充屬性,發現依賴a,然後依次去每級快取中獲取,由於**快取中已經有乙個a,於是b可以順利注入依賴,並被正確的初始化,然後遞迴返回,於是a也可以被正確的初始化了。
通過上述說明,可以看出bean都是需要可以先被例項化才可以的,所以這也就是為什麼構造器依賴可能會失敗的原因。假如a構造器依賴b,因為例項化a需要先呼叫a的建構函式,發現依賴b,那麼需要去初始化b,但是b也依賴a,不管b是通過構造器注入還是setter注入,此時由於a沒有被例項化,沒有放入**快取,所以b無法被初始化,所以spring會直接報錯。反之,如果a通過setter注入的話,那麼則可以通過建構函式先例項化,放入快取,然後再填充屬性,這樣的話不管b是通過setter還是構造器注入a,都能在快取中獲取到,於是可以初始化。
由此可見,迴圈依賴中,如果spring先去建立的bean通過構造器注入另乙個bean則會失敗,反之則可以成功。所以這也是為什麼一定不好通過構造器注入的原因。
參考:
spring解決迴圈依賴
或者原型 prototype 的場景是不支援迴圈依賴的,丟擲異常。基於構造器的迴圈依賴,是不存在的。那麼預設單例的屬性注入場景,spring是如何支援迴圈依賴的?首先,spring內部維護了三個map,也就是我們通常說的 快取。在spring的defaultsingletonbeanregistry...
spring解決迴圈依賴
之前面試有被問到過,面試官很調皮,我擅長的點沒有問,然後抽了乙個點讓我回答,這個點考察了原始碼的理解,當時只是大概記得是提前暴露,但是細節答得有些粗糙,特補充一下,protected object getsingleton string beanname,boolean allowearlyrefe...
spring迴圈依賴的解決
當a類中有b屬性,b類中有a屬性的時候,就會產生迴圈依賴。a在例項化的時候,引用了b,但是b麼有例項化,所以就會先例項化b,這個時候發現b又引用了a,但是a還沒有例項化,所以就造成了迴圈依賴。我們來看看spring是如何解決的 public class classa public classa pu...