Spring使用三級(jí)緩存解決循環(huán)依賴的問題
Spring如何使用三級(jí)緩存解決循環(huán)依賴在沒開始文章之前首先來了解一下什么是循環(huán)依賴
@Component public class A { @Autowired B b; } @Component public class B { @Autowired A a; }
在對(duì)象A創(chuàng)建過程中,需要注入B,因?yàn)槿萜髦袥]有B,則去創(chuàng)建B,B創(chuàng)建過程中又需要注入A,而A在等待B的創(chuàng)建,B在等待A的創(chuàng)建,導(dǎo)致兩者都無法創(chuàng)建成功,無法加入到單例池供用戶使用。
Spring則通過三級(jí)緩存來解決循環(huán)依賴的問題,另外如果對(duì)象的作用范圍是Prototype,則無法通過三級(jí)緩存解決循環(huán)依賴,會(huì)拋出BeanCurrentlyInCreationException
異常,構(gòu)造注入的方式,也無法解決循環(huán)依賴,只有set注入可以解決。
那么三級(jí)緩存又是什么呢?
三級(jí)緩存就是三個(gè)Map
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { //一級(jí)緩存(單例池,經(jīng)過完成生命周期的對(duì)象會(huì)放入其中) private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //二級(jí)緩存(剛實(shí)例化還未初始化的原始對(duì)象會(huì)放入其中) private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); //三級(jí)緩存(存放創(chuàng)建某個(gè)對(duì)象的工廠) private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
Spring Bean對(duì)象從創(chuàng)建到初始化大致會(huì)經(jīng)過四個(gè)流程
getSingleton()
、doCreateBean()
、populateBean()
、addSingleton()
getSingleton
:從單例池中獲取bean對(duì)象,如果沒有,則進(jìn)行創(chuàng)建doCreateBean()
:創(chuàng)建bean對(duì)象populateBean()
:填充依賴,如果被填充的對(duì)象不存在于單例池,則進(jìn)行創(chuàng)建等四個(gè)流程addSingleton()
:將初始化完成的對(duì)象加入到單例池
循環(huán)依賴的對(duì)象在三級(jí)緩存中的遷移過程
- A 創(chuàng)建過程中需要 B, 于是 A 將自己放到三級(jí)緩存里面,去實(shí)例化 B
- B 實(shí)例化的時(shí)候發(fā)現(xiàn)需要 A,于是 B 先查一級(jí)緩存,沒有,再查二級(jí)緩存,還是沒有,再查三級(jí)緩存
- 找到了A,然后把三級(jí)緩存中的 A 放到二級(jí)緩存,并刪除三級(jí)緩存中的 A
- B 順利初始化完畢,將自己放到一級(jí)緩存中(此時(shí) B 中的 A 還是創(chuàng)建中狀態(tài),并沒有完全初始化),刪除三級(jí)緩存中的 B
然后接著回來創(chuàng)建 A,此時(shí) B 已經(jīng)完成創(chuàng)建,直接從一級(jí)緩存中拿到 B,完成 A 的創(chuàng)建,并將 A 添加到單例池,刪除二級(jí)緩存中的 A
圖示:
以上就是Spring使用三級(jí)緩存解決循環(huán)依賴的詳細(xì)內(nèi)容,更多關(guān)于Spring循環(huán)依賴的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
mybatis的大于小于號(hào)轉(zhuǎn)義符號(hào)一覽
這篇文章主要介紹了mybatis的大于小于號(hào)轉(zhuǎn)義符號(hào)一覽,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java中的延遲隊(duì)列DelayQueue詳細(xì)解析
這篇文章主要介紹了Java中的延遲隊(duì)列DelayQueue詳細(xì)解析,JDK自身支持延遲隊(duì)列的數(shù)據(jù)結(jié)構(gòu),其實(shí)類:java.util.concurrent.DelayQueue,<BR>我們通過閱讀源碼的方式理解該延遲隊(duì)列類的實(shí)現(xiàn)過程,需要的朋友可以參考下2023-12-12Spring中的DeferredImportSelector實(shí)現(xiàn)詳解
這篇文章主要介紹了Spring中的DeferredImportSelector實(shí)現(xiàn)詳解,兩個(gè)官方的實(shí)現(xiàn)類AutoConfigurationImportSelector和ImportAutoConfigurationImportSelector都是Spring Boot后新增的實(shí)現(xiàn),需要的朋友可以參考下2024-01-01深入探討Druid動(dòng)態(tài)數(shù)據(jù)源的實(shí)現(xiàn)方式
Druid是一個(gè)高性能的實(shí)時(shí)分析數(shù)據(jù)庫,它可以處理大規(guī)模數(shù)據(jù)集的快速查詢和聚合操作,在Druid中,動(dòng)態(tài)數(shù)據(jù)源是一種可以在運(yùn)行時(shí)動(dòng)態(tài)添加和刪除的數(shù)據(jù)源,使用動(dòng)態(tài)數(shù)據(jù)源,您可以在Druid中輕松地處理不斷變化的數(shù)據(jù)集,本文講給大家介紹一下Druid動(dòng)態(tài)數(shù)據(jù)源該如何實(shí)現(xiàn)2023-08-08Spring高級(jí)注解@PropertySource詳細(xì)解讀
這篇文章主要介紹了Spring高級(jí)注解@PropertySource詳細(xì)解讀,@PropertySource注解用于指定資源文件讀取的位置,它不僅能讀取properties文件,也能讀取xml文件,并且通過YAML解析器,配合自定義PropertySourceFactory實(shí)現(xiàn)解析yaml文件,需要的朋友可以參考下2023-11-11