Spring使用三級緩存解決循環(huán)依賴的問題
Spring如何使用三級緩存解決循環(huán)依賴在沒開始文章之前首先來了解一下什么是循環(huán)依賴
@Component
public class A {
@Autowired
B b;
}
@Component
public class B {
@Autowired
A a;
}
在對象A創(chuàng)建過程中,需要注入B,因為容器中沒有B,則去創(chuàng)建B,B創(chuàng)建過程中又需要注入A,而A在等待B的創(chuàng)建,B在等待A的創(chuàng)建,導致兩者都無法創(chuàng)建成功,無法加入到單例池供用戶使用。
Spring則通過三級緩存來解決循環(huán)依賴的問題,另外如果對象的作用范圍是Prototype,則無法通過三級緩存解決循環(huán)依賴,會拋出BeanCurrentlyInCreationException異常,構(gòu)造注入的方式,也無法解決循環(huán)依賴,只有set注入可以解決。
那么三級緩存又是什么呢?
三級緩存就是三個Map
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//一級緩存(單例池,經(jīng)過完成生命周期的對象會放入其中)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//二級緩存(剛實例化還未初始化的原始對象會放入其中)
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//三級緩存(存放創(chuàng)建某個對象的工廠)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
Spring Bean對象從創(chuàng)建到初始化大致會經(jīng)過四個流程
getSingleton()、doCreateBean()、populateBean()、addSingleton()
getSingleton:從單例池中獲取bean對象,如果沒有,則進行創(chuàng)建doCreateBean():創(chuàng)建bean對象populateBean():填充依賴,如果被填充的對象不存在于單例池,則進行創(chuàng)建等四個流程addSingleton():將初始化完成的對象加入到單例池
循環(huán)依賴的對象在三級緩存中的遷移過程
- A 創(chuàng)建過程中需要 B, 于是 A 將自己放到三級緩存里面,去實例化 B
- B 實例化的時候發(fā)現(xiàn)需要 A,于是 B 先查一級緩存,沒有,再查二級緩存,還是沒有,再查三級緩存
- 找到了A,然后把三級緩存中的 A 放到二級緩存,并刪除三級緩存中的 A
- B 順利初始化完畢,將自己放到一級緩存中(此時 B 中的 A 還是創(chuàng)建中狀態(tài),并沒有完全初始化),刪除三級緩存中的 B
然后接著回來創(chuàng)建 A,此時 B 已經(jīng)完成創(chuàng)建,直接從一級緩存中拿到 B,完成 A 的創(chuàng)建,并將 A 添加到單例池,刪除二級緩存中的 A
圖示:

以上就是Spring使用三級緩存解決循環(huán)依賴的詳細內(nèi)容,更多關于Spring循環(huán)依賴的資料請關注腳本之家其它相關文章!
相關文章
mybatis如何實現(xiàn)的數(shù)據(jù)庫排序
這篇文章主要介紹了mybatis如何實現(xiàn)的數(shù)據(jù)庫排序,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
Mybatis-plus如何通過反射實現(xiàn)動態(tài)排序不同字段功能
這篇文章主要介紹了Mybatis-plus如何通過反射實現(xiàn)動態(tài)排序不同字段功能,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02
JavaEE中關于ServletConfig的小結(jié)
ServletConfig是針對特定的Servlet的參數(shù)或?qū)傩浴ervletConfig是表示單獨的Servlet的配置和參數(shù),只是適用于特定的Servlet。從一個servlet被實例化后,對任何客戶端在任何時候訪問有效,但僅對本servlet有效,一個servlet的ServletConfig對象不能被另一個servlet訪問2014-10-10
Java字符串格式化功能?String.format用法詳解
String類的format()方法用于創(chuàng)建格式化的字符串以及連接多個字符串對象,熟悉C語言的同學應該記得C語言的sprintf()方法,兩者有類似之處,format()方法有兩種重載形式2024-09-09
FreeMarker如何調(diào)用Java靜態(tài)方法及靜態(tài)變量方法
這篇文章主要介紹了FreeMarker如何調(diào)用Java靜態(tài)方法及靜態(tài)變量方法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
Spring @Component自定義注解實現(xiàn)詳解
@Component是一個元注解,意思是可以注解其他類注解,如@Controller @Service @Repository @Aspect。官方的原話是:帶此注解的類看為組件,當使用基于注解的配置和類路徑掃描的時候,這些類就會被實例化2022-09-09
Java統(tǒng)計一個字符串在另外一個字符串出現(xiàn)次數(shù)的方法
這篇文章主要介紹了Java統(tǒng)計一個字符串在另外一個字符串出現(xiàn)次數(shù)的方法,涉及java字符串遍歷、正則匹配等相關操作技巧,需要的朋友可以參考下2018-03-03

