Springboot循環(huán)依賴的原因及解決
什么是循環(huán)依賴
循環(huán)依賴(Circular Dependency) 是指兩個或多個 Bean 相互直接或間接依賴,導致容器無法正常初始化這些 Bean。
@Service public class ServiceA { @Autowired private ServiceB serviceB; // ServiceA 依賴 ServiceB } @Service public class ServiceB { @Autowired private ServiceA serviceA; // ServiceB 依賴 ServiceA }
Spring Boot 基于 Spring 框架,其循環(huán)依賴的處理機制與 Spring 一致,但在 Spring Boot 2.6+ 版本中默認禁止了循環(huán)依賴(通過 spring.main.allow-circular-references=false
)。
產(chǎn)生循環(huán)依賴的原因
1.構造函數(shù)注入循環(huán)依賴:
@Service public class ServiceA { private final ServiceB serviceB; public ServiceA(ServiceB serviceB) { // 構造函數(shù)注入 this.serviceB = serviceB; } } @Service public class ServiceB { private final ServiceA serviceA; public ServiceB(ServiceA serviceA) { // 構造函數(shù)注入 this.serviceA = serviceA; } }
直接報錯:構造函數(shù)注入的循環(huán)依賴無法解決,容器啟動時拋出
BeanCurrentlyInCreationException
。
2.Setter/Field 注入循環(huán)依賴:
在spring中使用@Autowired注解標簽進行自動注入,如果不加以處理,會出現(xiàn)循環(huán)依賴問題 。
怎么解決循環(huán)依賴
在Springboot2.5以前可以通過三級緩存解決單例 Bean 的循環(huán)依賴問題。
緩存名稱 | 職責 |
---|---|
singletonObjects | 存放完全初始化好的 Bean(一級緩存) |
earlySingletonObjects | 存放提前暴露的早期 Bean(二級緩存) |
singletonFactories | 存放 Bean 的工廠對象(三級緩存) |
以最初的ServiceA與ServiceB為例,
創(chuàng)建
ServiceA
,通過工廠將其半成品引用存入三級緩存。ServiceA
注入ServiceB
,觸發(fā)ServiceB
的創(chuàng)建。創(chuàng)建
ServiceB
,同樣將其半成品引用存入三級緩存。ServiceB
注入ServiceA
時,從三級緩存中獲取ServiceA
的早期引用,完成ServiceB
的初始化。ServiceB
初始化完成后,ServiceA
完成依賴注入,最終初始化。
出現(xiàn)循環(huán)依賴之后的幾個解決思路:
1.避免循環(huán)依賴(推薦)
重構代碼:將公共邏輯抽離到第三個 Bean 中。
使用接口或抽象類:通過面向接口編程解耦具體實現(xiàn)。
2. 允許循環(huán)依賴(臨時方案)
在 application.properties
中顯式允許循環(huán)依賴:
# Spring Boot 2.6+ 需要手動開啟 spring.main.allow-circular-references=true
這種只適用于Springboot版本在2.6以上的循環(huán)依賴被禁止的情形。
3. 使用 @Lazy
延遲加載
在其中一個依賴上添加 @Lazy
,延遲注入 Bean 的初始化:
@Service public class ServiceA { @Lazy @Autowired private ServiceB serviceB; // 延遲初始化 ServiceB }
4. 調整注入方式
優(yōu)先使用 Setter/Field 注入:避免構造函數(shù)注入導致的不可解循環(huán)依賴。
@Service public class ServiceA { private ServiceB serviceB; @Autowired public void setServiceB(ServiceB serviceB) { // Setter 注入 this.serviceB = serviceB; } }
使用setter注入
循環(huán)依賴的局限性
構造函數(shù)注入無法解決循環(huán)依賴:Spring 容器在創(chuàng)建 Bean 時需先完成構造函數(shù)調用,此時依賴的 Bean 尚未初始化。
原型(Prototype)作用域的 Bean:Spring 不管理原型 Bean 的完整生命周期,無法解決其循環(huán)依賴。
AOP 代理問題:如果 Bean 被 AOP 代理(如
@Async
、@Transactional
),可能導致循環(huán)依賴解決失敗。
總結
Spring Boot 的循環(huán)依賴本質是 Spring 框架的機制問題,解決核心在于:
理解三級緩存的工作原理。
優(yōu)先通過代碼設計避免循環(huán)依賴。
必要時合理使用
@Lazy
或調整注入方式。
盡可能在設計之初就避免循環(huán)依賴
到此這篇關于Springboot循環(huán)依賴的原因及解決的文章就介紹到這了,更多相關Springboot循環(huán)依賴內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mybatis 集合嵌套查詢和集合嵌套結果的區(qū)別說明
這篇文章主要介紹了mybatis 集合嵌套查詢和集合嵌套結果的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09SpringBoot實現(xiàn)多個子域共享cookie的示例
本文主要介紹了SpringBoot實現(xiàn)多個子域共享cookie的示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04Jenkins Pipeline為Kubernetes應用部署增加狀態(tài)檢測腳本優(yōu)化
這篇文章主要為大家介紹了Jenkins Pipeline為Kubernetes應用部署增加狀態(tài)檢測腳本優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12