網站首頁 編程語言 正文
什么叫循環依賴:簡單來說,在spring中對象的創建管理都是IOC容器幫我們做的,以默認單例的方式幫我們創建bean,但是會出現一個問題:對象A里面有個屬性是B對象,B對象里面又有一個A對象。如下
class A {
private B b;
}
class B{
private A a;
}
不管先創建哪個對象,在屬性賦值時都要需要另一個對象。假設創建A對象,需要屬性賦值的時候,發現需要B對象,去創建B對象的時候,發現需要A對象,此時A對象還未創建完,這樣就形成了一個簡單的循環依賴問題。
流程圖:
? ????????此時容器中當然沒有A和B對象,可以發現此時已經形成了一個閉環,也就是循環依賴。解決的關鍵在于:下圖的最后一步沒找到
?此時若能解決此處的問題,閉環將被打破。關鍵點在于此時A對象已經實例化了,但還未完成初始化(半成品對象)。
?????????這時候,請思考一個問題,如果我們持有一個對象的引用(C中的指針),能否在后續的步驟中給這個對象進行賦值操作?
當然是可以的,在這個問題的基礎上,我們可以引入一個東西,來解決循環依賴,就是大家所熟悉的緩存。稍稍加點改動,只需要我們實例化后將對象放入緩存,從容器中查找時,也查找緩存就可以解決循環依賴。此時B已經是成品對象了并且在緩存中,然后A對象就可以完成初始化了。
?當然成品對象和半成品對象放在一起怎么看都不合適,所以spring中解決循環依賴是:三級緩存和提前暴露。其實最核心的是實例化和初始化分開進行。
spring三級緩存源碼:
//一級緩存,保存beanName和創建Bean直接實例的關系(保存成熟對象)
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
//三級緩存,保存beanName和創建Bean的工廠之間的關系(第二個是一個函數式接口的類型)
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
//二級緩存,保存保存beanName和創建Bean直接實例的關系(半成品對象)
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
簡述下過程:
A首先完成了初始化的第一步,而且將本身提早曝光到singletonFactories中,此時進行初始化的第二步,發現本身依賴對象B,此時就嘗試去get(B),發現B尚未被create,因此走create流程,B在初始化第一步的時候發現本身依賴了對象A,因而嘗試get(A),嘗試一級緩存singletonObjects(確定沒有,由于A還沒初始化徹底),嘗試二級緩存earlySingletonObjects(也沒有),嘗試三級緩存singletonFactories,因為A經過ObjectFactory將本身提早曝光了,因此B可以經過ObjectFactory.getObject拿到A對象(半成品),B拿到A對象后順利完成了初始化階段一、二、三,徹底初始化以后將本身放入到一級緩存singletonObjects中。此時返回A中,A此時能拿到B的對象順利完成本身的初始化階段二、三,最終A也完成了初始化,進去了一級緩存singletonObjects中,因為B拿到了A的對象引用,因此B里面A對象完成了初始化。
?注意事項:
1.Spring只是解決了單例模式下屬性依賴的循環問題;Spring為了解決單例的循環依賴問題,使用了三級緩存。
2.多實例Bean是每次調用一次getBean都會執行一次構造方法并且給屬性賦值,根本沒有三級緩存,因此不能解決循環依賴。
原文鏈接:https://blog.csdn.net/weixin_71419462/article/details/126169103
相關推薦
- 2022-05-17 qt 錯誤GL/gl.h: No such file or directory的解決方法
- 2021-11-10 Android?Studio設置繪制布局時的視圖_Android
- 2022-11-24 GoLang切片相關問題梳理講解_Golang
- 2022-11-20 C++遞歸算法處理島嶼問題詳解_C 語言
- 2022-11-01 Flask模板渲染與Get和Post請求詳細介紹_python
- 2022-06-30 C++?select模型簡單聊天室的實現示例_C 語言
- 2022-07-30 Python?excel合并居中值相同的單元格實例代碼_python
- 2022-05-01 React的三大屬性你都知道嗎_React
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支