亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

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

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

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

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

循環(huán)依賴指兩個或多個Bean相互直接或間接引用,形成閉環(huá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 核心危害

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

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

二、Spring的三級緩存機制

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

2.1 三級緩存結構

緩存級別存儲內容
一級緩存(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 避免構造器注入循環(huán)

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

// 錯誤示例:啟動直接失敗  
@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;  
    }  
}  

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

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

3.2 使用Setter/Field注入

將構造器注入改為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被代理,首次調用時才會真實初始化。

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)化:設計模式應用

4.1 依賴倒置原則(DIP)

高層模塊不應依賴低層模塊,二者都應依賴抽象

// 定義數(shù)據(jù)訪問接口  
public interface UserRepository {  
    User findById(Long id);  
}  
// 高層服務依賴接口  
@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)細節(jié)  
}  

4.2 事件驅動模型

通過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) {  
        // 處理邏輯  
    }  
}  

五、檢測與預防工具

5.1 IDE檢測

  • IntelliJ IDEA:自動標記循環(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 架構規(guī)范

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

六、常見問題解答

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

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

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

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

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

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

七、總結與最佳實踐

黃金法則

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

緊急修復流程

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

工具推薦

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

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

相關文章

  • 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等等。本文為大家詳細講講工具類如何獲取到Spring容器中的Bean,需要的可以參考一下
    2022-07-07
  • Spring5新特性之Reactive響應式編程

    Spring5新特性之Reactive響應式編程

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

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

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

    Springboot Redis設置key前綴的方法步驟

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

    Java如何獲取相對路徑文件

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

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

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

    關于idea中ssm框架的編碼問題分析

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

    Java訪問者設計模式詳細講解

    大多數(shù)情況下你不需要訪問者模式,但當一旦需要訪問者模式時,那就是真的需要它了,這是設計模式創(chuàng)始人的原話??梢钥闯鰬脠鼍氨容^少,但需要它的時候是不可或缺的,這篇文章就開始學習最后一個設計模式——訪問者模式
    2022-11-11

最新評論