當前位置:編程學習大全網 - 源碼下載 - Spring是如何解決循環依賴的?

Spring是如何解決循環依賴的?

妳需要我,我需要妳就是循環依賴

在Spring中使用的三級緩存來解決循環依賴問題,這裏的緩存其實就是Map對象

當獲取壹個Bean時會先從緩存中查找是否有相應的Bean。

1 創建A實例

2 將A實例(半初始化,屬性沒有填充)暴露放入緩存中

3 填充A實例的屬性

4 A實例屬性依賴B對象

5 創建B對象實例

6 填充B實例屬性

7 B實例屬性依賴A對象

8 將上面已經暴露到三級緩存中的A對象註入給B實例

在獲取A對象的時候執行上面27.1中的getSingleton方法,會將三級緩存中A這個半初始化狀態的對象移除,將其存入到二級緩存中。

9 B實例Bean的創建工作繼續執行初始化方法

B如果需要AOP代理?最終B對象是個代理對象。B到此就完全的初始化完了,B的依賴對象A此時是個半初始化狀態的對象

10 B實例對象保存到壹級緩存

最終B實例創建,初始化都執行完後會將自身加入到壹級緩存同時清除二級,三級緩存

11 A實例Bean創建繼續執行

如果B是被AOP代理的那麽此時的A實例註入的B對象就是壹個代理對象。

12 A實例Bean執行初始化方法

13 A繼續執行上面的10步驟

三級緩存解決問題:循環依賴+AOP問題

只用壹,二級緩存:

從上面羅列的步驟看似乎很是完美解決了循環依賴問題,接下來我們看看加入AOP的場景

假如A,B兩個對象最終都是要被AOP代理的

執行到這裏,A中依賴的B是代理對象沒有問題,但是B中依賴的A對象是原始對象;這就不正確了應該依賴的A也必須是代理對象才是。

引入三級緩存:

三級緩存引入了ObjectFactory對象,在獲取對象的時候,是調用ObjectFactory#getObject方法。

而這個getObject方法的實現實際執行的是getEarlyBeanReference方法,再來回顧下:

在創建實例時先將其存入三級緩存中:

getEarlyBeanReference方法就是提前創建代理對象

如果開啟了AOP代理後

通過getEarlyBeanReference方法提前創建代理對象。這樣就解決了循環依賴時AOP代理問題。保證獲取的都是同壹個對象。

其實引入三級緩存還解決了壹個問題就是延遲代理對象的創建,如果不應用ObjectFactory方式那麽我們需要不管需不需要都要先創建代理對象,而引入ObjectFactory可以在註入的時候先暴露的是ObjectFactory只有在調用getObject方法的時候才去創建真正的代理對象(避免了所有Bean都強制創建代理對象)。當沒有被代理時可以直接返回原始對象,如果被代理會提前創建代理對象。

不用二級直接是用壹,三級緩存?

假設場景:A 依賴 B,B 依賴 A、C,C 依賴 A

如果這樣會出現不同的代理對象,每次調用getObject都會創建不同的代理對象(在上面的場景中如果只用壹,三級緩存那麽 B 依賴 A會通過getObject獲取壹個代理對象Proxy$1,接著註入C的時候 C中又依賴A,那這時候又從getObject獲取對象那麽返回的將又會是壹個新的代理對象Proxy$2;在這個過程中A對象就出現了2個不壹樣的對象了,這肯定是錯誤的)。而引入二級緩存也就解決了這個問題。只有二級緩存沒有的時候才從三級緩存匯總獲取(如果需要則創建代理對象,然後保存到二級緩存中,二級緩存中已經是提前創建了代理對象(如果需要代理))。

當壹個Bean完全的創建完以後放入壹級緩存中,此時會吧二級三級中的緩存清除。

完畢!!!!

SpringMVC參數統壹驗證方法

SpringBoot多數據源配置詳解

SpringCloud Nacos 整合feign

Spring AOP動態代理失效的解決方法@Transactional為何會失效

SpringBoot配置文件妳了解多少?

SpringBoot郵件發送示例 Springboot面試題整理附答案

SpringBoot項目查看線上日誌

在Spring Cloud 中妳還在使用Ribbon快來試試Load-Balancer

SpringBoot分庫分表sharding-sphere3

  • 上一篇:妳極有可能有彩票焦慮!妳知道什麽是彩票焦慮嗎?
  • 下一篇:幫幫我,config.plist怎麽配置朋友們?
  • copyright 2024編程學習大全網