Spring三級緩存解決循環依賴

前提知識1、解決循環依賴的核心依據:實例化和初始化步驟是分開執行的
2、實現方式:三級緩存
3、lambda表達式的延遲執行特性
spring源碼執行邏輯

Spring三級緩存解決循環依賴

文章插圖
核心方法refresh(), populateBean()填充bean對象 , 設置屬性值;
getEarlyBeanReference() 在未完成屬性賦值之前,提前暴露代理對象,在賦值的時候才確定真實對象 。
Spring三級緩存解決循環依賴

文章插圖
1、三個map結構分別存儲什么類型的對象?
Spring三級緩存解決循環依賴

文章插圖
-級緩存:成品對象
級緩存:半成品對象
三級緩存:lambda表達式
2、三個map結構在進行對象查找的時候,查找的順序是什么樣的?
1,2,3
3、為什么一級緩存有對象之后就要把二級和三級給移除掉?
Spring三級緩存解決循環依賴

文章插圖
因為對象的查找順序是1,2 , 3,如果在一級中找到了,那么二級永遠也不會進行查找,以此類推
【Spring三級緩存解決循環依賴】4、如果只有一個map結構 , 能否解決循環依賴問題?
原則上是可以的,但是操作起來比較麻煩,當只有一個map結構的時候就意味著成品對象和半成品對象要放到一起 , 而半成品對象是不能暴露給外部使用的,要不會報空指針異常,所以需要添加標識位,而容器中對象的名字都是固定的,所以標識位只能在value中,也就意味著每次在判斷的時候都要獲取到value然后判斷完標志位之后才能進行下一步操作,比較麻煩,直接用兩個map可以輕松解決這個問題
5、如果只有兩個map結構,能否解決循環依賴問題?
原則上是可以的 , 但是有前提條件:整個代碼的執行邏輯中不能包含代理對象的創建,否則會報錯
6、為什么必須要使用三個map結構來解決循環依賴問題?三級緩存是如何解決循環依賴問題的?
(1)在創建代理對象的時候是否需要創建原始對象?
需要
(2)容器中能否同時存在兩個同名的不同對象?
不能
(3)如果創建出了代理對象 , 那么原始對象應該怎么處理?
當創建出代理對象之后 , 需要將代理對象覆蓋原始對象
(4)那么為什么要引入三級緩存呢?為什么要傳入一個lambda表達式呢?
正常的bean的生命周期是先通過createBeanlnstance創建出原始對象,然后在populateBean的方法中完成對象屬性的賦值工作,然后在BeanPostProcessor的后置處理方法中完成代理對象的創建工作,也就是說按照正常的執行邏輯,是完成屬性的賦值之后才會創建出代理對象,那么意味著最后創建出的是代理對象,但是賦值的時候賦的是原始對象,所以會出現一個錯誤:that said other beans do not use the final version of the bean. 當引入lambda表達式之后相當于將生成代理對象的過程給提前了 , 也就是說在完成對象的屬性賦值的時候必須要唯一性的確定好我需要的到底是代理對象還是原始對象,參考 (getEarlyBeanReference方法)也就是說我們在賦值的前一刻必須要確定好最終的結果,但是又因為我們沒有辦法確定什么時刻會給什么對象的屬性賦值,所以采用lambda表達式的方法延遲執行,只有在對象賦值的最后一刻才確定出到底是什么對象 。
Spring三級緩存解決循環依賴

文章插圖

    推薦閱讀