Spring中如何解決迴圈依賴

MuXinu發表於2024-03-30

八字真言:“三級快取,提前暴露”

此文只是介紹簡單的情況便於理解,實際上場景會更復雜、情況會更多,但是原理相通。

一、什麼是迴圈依賴?

從字面上來理解就是A依賴B的同時B也依賴了A,就像下面這樣
0
上圖是簡單的迴圈依賴,也會存在A依賴B,B依賴C,C依賴A這種迴圈,或者更復雜的情況。
(在實際工作中應該儘量避免出現迴圈依賴的情況)

二、什麼情況下迴圈依賴可以被處理?

0

三、Spring是如何解決的迴圈依賴?

三級快取:

一級快取 : Map<string,object> singletonObjects,單例池,用於儲存例項化、屬性賦值(注入)、初始化完成的 bean 例項
二級快取 : Map<string,object> earlySingletonObjects,早期曝光物件,用於儲存例項化完成的 bean 例項
三級快取 : Map<string,objectfactory<?>> singletonFactories,早期曝光物件工廠,用於儲存 bean 建立工廠,以便於後面擴充套件有機會建立代理物件。

流程圖:

0

總結:

假如testService1依賴testService2,testService2依賴testService1
Bean初始化流程:
  1. 建立 testService1例項,例項化的時候把 testService1 物件⼯⼚放⼊三級快取,並提前先暴露出來;
  2. testService1 注⼊屬性時,發現依賴 testService2,此時 testService2 還沒有被建立出來,所以去例項化 testService2;
  3. 同樣,testService2注⼊屬性時發現依賴 testService1,它就會從快取裡找 testService1物件。依次從⼀級到三級快取查詢 testService1,從三級快取透過物件⼯⼚拿到 testService1,發現 testService1雖然不太完善,但是存在,把 testService1 放⼊⼆級快取,同時刪除三級快取中的 testService1,此時,testService2 已經例項化並且初始化完成,把testService2放入⼀級快取
  4. 接著testService1繼續屬性賦值,順利從⼀級快取拿到例項化且初始化完成的testService2物件,testService1物件建立也完成,刪除⼆級快取中的 testService1,同時把testService1放⼊⼀級快取
  5. 最後,⼀級快取中儲存著例項化、初始化都完成的 testService1、testService2 物件

相關文章