欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring?Boot循環(huán)依賴原理、解決方案與最佳實踐(全解析)

 更新時間:2025年04月17日 11:24:22   作者:weixin_52318532  
循環(huán)依賴指兩個或多個Bean相互直接或間接引用,形成閉環(huán)依賴關(guān)系,這篇文章主要介紹了Spring?Boot循環(huán)依賴原理、解決方案與最佳實踐(全解析),需要的朋友可以參考下

?? Spring Boot循環(huán)依賴全解析:原理、解決方案與最佳實踐

#SpringBoot核心 #依賴注入 #設(shè)計模式 #性能優(yōu)化

一、循環(huán)依賴的本質(zhì)與危害

1.1 什么是循環(huán)依賴?

循環(huán)依賴指兩個或多個Bean相互直接或間接引用,形成閉環(huán)依賴關(guān)系。
典型場景

@Service  
public class ServiceA {  
    @Autowired  
    private ServiceB serviceB;  
}  
@Service  
public class ServiceB {  
    @Autowired  
    private ServiceA serviceA;  
}  

Spring啟動時拋出異常:

BeanCurrentlyInCreationException: Error creating bean with name 'serviceA':  
Requested bean is currently in creation: Is there an unresolvable circular reference?  

1.2 核心危害

  • 應(yīng)用啟動失敗:Spring無法完成Bean初始化
  • 設(shè)計缺陷信號:模塊職責(zé)不清,耦合度過高
  • 潛在性能問題:即使解決循環(huán)依賴,可能引發(fā)隱藏的初始化順序問題

pring無法完成Bean初始化設(shè)計缺陷信號:模塊職責(zé)不清,耦合度過高潛在性能問題:即使解決循環(huán)依賴,可能引發(fā)隱藏的初始化順序問題

二、Spring的三級緩存機制

Spring通過三級緩存解決Setter/Field注入的循環(huán)依賴,但無法解決構(gòu)造器注入的循環(huán)依賴。

2.1 三級緩存結(jié)構(gòu)

緩存級別存儲內(nèi)容
一級緩存(singletonObjects)完全初始化的Bean
二級緩存(earlySingletonObjects)提前暴露的早期Bean(未完成屬性填充)
三級緩存(singletonFactories)Bean工廠對象(用于生成早期引用)

 2.2 解決流程(以ServiceA和ServiceB為例)

1. 創(chuàng)建ServiceA → 將原始對象工廠放入三級緩存  
2. 填充ServiceA屬性 → 發(fā)現(xiàn)需要ServiceB  
3. 創(chuàng)建ServiceB → 將原始對象工廠放入三級緩存  
4. 填充ServiceB屬性 → 從三級緩存獲取ServiceA的工廠 → 生成代理對象  
5. ServiceB初始化完成 → 移入一級緩存  
6. ServiceA繼續(xù)填充ServiceB → 從一級緩存獲取ServiceB → 完成初始化  

三、解決方案與代碼實戰(zhàn)

3.1 避免構(gòu)造器注入循環(huán)

構(gòu)造器注入循環(huán)依賴無法解決(Spring 5.3+默認(rèn)禁止):

// 錯誤示例:啟動直接失敗  
@Service  
public class ServiceA {  
    private final ServiceB serviceB;  
    public ServiceA(ServiceB serviceB) {  
        this.serviceB = serviceB;  
    }  
}  
@Service  
public class ServiceB {  
    private final ServiceA serviceA;  
    public ServiceB(ServiceA serviceA) {  
        this.serviceA = serviceA;  
    }  
}  

強制允許構(gòu)造器循環(huán)依賴(不推薦)

# application.properties  
spring.main.allow-circular-references=true  

3.2 使用Setter/Field注入

將構(gòu)造器注入改為Setter注入:

@Service  
public class ServiceA {  
    private ServiceB serviceB;  
    @Autowired  
    public void setServiceB(ServiceB serviceB) {  
        this.serviceB = serviceB;  
    }  
}  
@Service  
public class ServiceB {  
    private ServiceA serviceA;  
    @Autowired  
    public void setServiceA(ServiceA serviceA) {  
        this.serviceA = serviceA;  
    }  
}  

3.3 @Lazy延遲加載

強制延遲其中一個Bean的初始化:

@Service  
public class ServiceA {  
    @Lazy  
    @Autowired  
    private ServiceB serviceB;  
}  

原理:ServiceB被代理,首次調(diào)用時才會真實初始化。

3.4 接口抽象解耦

通過接口隔離實現(xiàn)類依賴

public interface IServiceA {  
    void doSomething();  
}  
public interface IServiceB {  
    void doAnother();  
}  
@Service  
public class ServiceAImpl implements IServiceA {  
    @Autowired  
    private IServiceB serviceB;  
}  
@Service  
public class ServiceBImpl implements IServiceB {  
    @Autowired  
    private IServiceA serviceA;  
}  

四、深度優(yōu)化:設(shè)計模式應(yīng)用

4.1 依賴倒置原則(DIP)

高層模塊不應(yīng)依賴低層模塊,二者都應(yīng)依賴抽象

// 定義數(shù)據(jù)訪問接口  
public interface UserRepository {  
    User findById(Long id);  
}  
// 高層服務(wù)依賴接口  
@Service  
public class UserService {  
    private final UserRepository repository;  
    public UserService(UserRepository repository) {  
        this.repository = repository;  
    }  
}  
// 低層實現(xiàn)  
@Repository  
public class JpaUserRepository implements UserRepository {  
    // 實現(xiàn)細(xì)節(jié)  
}  

4.2 事件驅(qū)動模型

通過ApplicationEvent解耦強依賴

// ServiceA發(fā)布事件  
@Service  
public class ServiceA {  
    @Autowired  
    private ApplicationEventPublisher publisher;  
    public void triggerEvent() {  
        publisher.publishEvent(new CustomEvent(this));  
    }  
}  
// ServiceB監(jiān)聽事件  
@Service  
public class ServiceB {  
    @EventListener  
    public void handleEvent(CustomEvent event) {  
        // 處理邏輯  
    }  
}  

五、檢測與預(yù)防工具

5.1 IDE檢測

  • IntelliJ IDEA:自動標(biāo)記循環(huán)依賴(需安裝Spring Assistant插件)
  • Eclipse:通過STS (Spring Tool Suite)插件提示

5.2 Maven插件分析

<plugin>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-maven-plugin</artifactId>  
    <configuration>  
        <excludes>  
            <exclude>  
                <groupId>org.projectlombok</groupId>  
                <artifactId>lombok</artifactId>  
            </exclude>  
        </excludes>  
    </configuration>  
</plugin>  

運行命令:

mvn spring-boot:run -Dspring-boot.run.profiles=dev  

5.3 架構(gòu)規(guī)范

  • 模塊化設(shè)計:按業(yè)務(wù)拆分模塊(如user-serviceorder-service
  • 依賴規(guī)則
    • 下層模塊可依賴上層
    • 同層禁止相互依賴
    • 通用工具類下沉至common模塊

六、常見問題解答

Q1:允許循環(huán)依賴對性能有影響嗎?

  • 短期影響:增加Bean創(chuàng)建時的上下文切換
  • 長期風(fēng)險:可能導(dǎo)致內(nèi)存泄漏(如未正確釋放代理對象)

Q2:@Lazy注解可以隨便用嗎?

  • 慎用場景:頻繁調(diào)用的Bean會增加代理開銷
  • 最佳實踐:僅用于解決無法重構(gòu)的歷史代碼

Q3:Spring為什么能解決Setter注入循環(huán)依賴?

  • 核心機制:三級緩存提前暴露未完成初始化的對象引用

七、總結(jié)與最佳實踐

黃金法則

  • 優(yōu)先使用構(gòu)造器注入:強制暴露依賴關(guān)系
  • 遵守單一職責(zé)原則:拆分超過500行代碼的類
  • 定期依賴審查:使用ArchUnit等工具檢測架構(gòu)規(guī)范

緊急修復(fù)流程

發(fā)現(xiàn)循環(huán)依賴 → 使用@Lazy臨時解決 → 標(biāo)記為技術(shù)債務(wù) → 排期重構(gòu)  

工具推薦

通過合理設(shè)計+規(guī)范約束,可有效避免循環(huán)依賴,構(gòu)建高可維護的Spring Boot應(yīng)用! ??

到此這篇關(guān)于Spring Boot循環(huán)依賴全解析:原理、解決方案與最佳實踐的文章就介紹到這了,更多相關(guān)Spring Boot循環(huán)依賴內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中的@EnableAutoConfiguration注解解析

    SpringBoot中的@EnableAutoConfiguration注解解析

    這篇文章主要介紹了SpringBoot中的@EnableAutoConfiguration注解解析,@EnableAutoConfiguration也是借助@Import的幫助,將所有符合自動配置條件的bean定義注冊到IoC容器,需要的朋友可以參考下
    2023-09-09
  • 如何將maven項目劃分為多個模塊

    如何將maven項目劃分為多個模塊

    這篇文章主要介紹了如何將maven項目劃分為多個模塊,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • Spring框架對于Bean的管理詳解

    Spring框架對于Bean的管理詳解

    在實際開發(fā)中,我們往往要用到Spring容器為我們提供的諸多資源,例如想要獲取到容器中的配置、獲取到容器中的Bean等等。本文為大家詳細(xì)講講工具類如何獲取到Spring容器中的Bean,需要的可以參考一下
    2022-07-07
  • Spring5新特性之Reactive響應(yīng)式編程

    Spring5新特性之Reactive響應(yīng)式編程

    這篇文章主要介紹了Spring5新特性之Reactive響應(yīng)式編程,響應(yīng)式編程是一種編程范式,通用和專注于數(shù)據(jù)流和變化的,并且是異步的,下文更多詳細(xì)內(nèi)容,需要的小伙伴可以參考一下,希望對你有所幫助
    2022-03-03
  • JAVA讀取二進制文件以及畫圖教程

    JAVA讀取二進制文件以及畫圖教程

    由于項目需要,需要對二進制文件進行讀取,所以這篇文章主要給大家介紹了關(guān)于JAVA讀取二進制文件以及畫圖的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Springboot Redis設(shè)置key前綴的方法步驟

    Springboot Redis設(shè)置key前綴的方法步驟

    這篇文章主要介紹了Springboot Redis設(shè)置key前綴的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Java如何獲取相對路徑文件

    Java如何獲取相對路徑文件

    這篇文章主要介紹了Java如何獲取相對路徑文件問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • java爬取并下載酷狗TOP500歌曲的方法

    java爬取并下載酷狗TOP500歌曲的方法

    這篇文章主要介紹了java爬取并下載酷狗TOP500歌曲的方法,非常具有實用價值,需要的朋友可以參考下
    2019-01-01
  • 關(guān)于idea中ssm框架的編碼問題分析

    關(guān)于idea中ssm框架的編碼問題分析

    在實際開發(fā)中需要將操作系統(tǒng)編碼、文件編碼、頁面編碼以及tomcat服務(wù)器編碼保持一致,而tomcat在默認(rèn)情況下是使用UTF-8,這就使得其打印的日志文件出現(xiàn)中文亂碼,因此在一般情況下,只需要將tomcat服務(wù)器的編碼改為GBK即可
    2021-06-06
  • Java訪問者設(shè)計模式詳細(xì)講解

    Java訪問者設(shè)計模式詳細(xì)講解

    大多數(shù)情況下你不需要訪問者模式,但當(dāng)一旦需要訪問者模式時,那就是真的需要它了,這是設(shè)計模式創(chuàng)始人的原話??梢钥闯鰬?yīng)用場景比較少,但需要它的時候是不可或缺的,這篇文章就開始學(xué)習(xí)最后一個設(shè)計模式——訪問者模式
    2022-11-11

最新評論