最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

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

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

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

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

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

Spring啟動(dòng)時(shí)拋出異常:

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

1.2 核心危害

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

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

二、Spring的三級(jí)緩存機(jī)制

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

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

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

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

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

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

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

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

// 錯(cuò)誤示例:?jiǎn)?dòng)直接失敗  
@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;  
    }  
}  

強(qiáng)制允許構(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延遲加載

強(qiáng)制延遲其中一個(gè)Bean的初始化:

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

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

3.4 接口抽象解耦

通過接口隔離實(shí)現(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è)計(jì)模式應(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;  
    }  
}  
// 低層實(shí)現(xiàn)  
@Repository  
public class JpaUserRepository implements UserRepository {  
    // 實(shí)現(xiàn)細(xì)節(jié)  
}  

4.2 事件驅(qū)動(dòng)模型

通過ApplicationEvent解耦強(qiáng)依賴

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

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

5.1 IDE檢測(cè)

  • IntelliJ IDEA:自動(dòng)標(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>  

運(yùn)行命令:

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

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

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

六、常見問題解答

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

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

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

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

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

  • 核心機(jī)制:三級(jí)緩存提前暴露未完成初始化的對(duì)象引用

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

黃金法則

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

緊急修復(fù)流程

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

工具推薦

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

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

相關(guān)文章

  • SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解

    SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解

    這篇文章主要介紹了SpringBoot增強(qiáng)Controller方法@ControllerAdvice注解的使用詳解,@ControllerAdvice,是Spring3.2提供的新注解,它是一個(gè)Controller增強(qiáng)器,可對(duì)controller進(jìn)行增強(qiáng)處理,需要的朋友可以參考下
    2023-10-10
  • Java對(duì)象存儲(chǔ)內(nèi)存布局詳解

    Java對(duì)象存儲(chǔ)內(nèi)存布局詳解

    眾所周知,Java是一門面向?qū)ο蟮恼Z言,那么一個(gè)對(duì)象在內(nèi)存中都包含什么東西呢,本文主要詳細(xì)介紹了Java對(duì)象的內(nèi)存布局,訪問定位,創(chuàng)建過程,線程安全,感興趣的小伙伴可以跟著小編一起來學(xué)習(xí)
    2023-04-04
  • 學(xué)生視角手把手帶你寫Java?線程池初版

    學(xué)生視角手把手帶你寫Java?線程池初版

    作者是一個(gè)來自河源的大三在校生,以下筆記都是作者自學(xué)之路的一些淺薄經(jīng)驗(yàn),如有錯(cuò)誤請(qǐng)指正,將來會(huì)不斷的完善筆記,幫助更多的Java愛好者入門
    2022-03-03
  • IDEA中Jar包的制作和使用方法

    IDEA中Jar包的制作和使用方法

    這篇文章主要介紹了IDEA的Jar包的制作和使用方法,文中補(bǔ)充介紹了idea的pom依賴配置后,不會(huì)自動(dòng)下載jar包的解決辦法,感興趣的朋友跟隨小編一起看看吧
    2025-04-04
  • java?for循環(huán)內(nèi)執(zhí)行多線程問題

    java?for循環(huán)內(nèi)執(zhí)行多線程問題

    這篇文章主要介紹了java?for循環(huán)內(nèi)執(zhí)行多線程問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 使用代碼生成器自定義Entity的部分注解

    使用代碼生成器自定義Entity的部分注解

    這篇文章主要介紹了使用代碼生成器自定義Entity的部分注解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • java如何解析/讀取xml文件

    java如何解析/讀取xml文件

    這篇文章主要為大家詳細(xì)介紹了java如何解析/讀取xml文件的方法,感興趣的小伙伴們可以參考一下
    2016-03-03
  • Java編程代碼性能優(yōu)化

    Java編程代碼性能優(yōu)化

    本文介紹了 Java 代碼優(yōu)化的過程,總結(jié)了優(yōu)化 Java 程序的一些最佳實(shí)踐,分析了進(jìn)行優(yōu)化的方法,并解釋了性能提升的原因,需要的朋友可以參考下
    2015-11-11
  • Java分別利用深度優(yōu)先和廣度優(yōu)先求解迷宮路徑

    Java分別利用深度優(yōu)先和廣度優(yōu)先求解迷宮路徑

    這篇文章主要為大家詳細(xì)介紹了Java如何利用深度優(yōu)先的非遞歸遍歷方法和廣度優(yōu)先的遍歷方法實(shí)現(xiàn)求解迷宮路徑,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-08-08
  • Java實(shí)現(xiàn)將彩色PDF轉(zhuǎn)為灰度PDF的示例代碼

    Java實(shí)現(xiàn)將彩色PDF轉(zhuǎn)為灰度PDF的示例代碼

    本文以Java代碼為例介紹如何實(shí)現(xiàn)將彩色PDF文件轉(zhuǎn)為灰度(黑白)的PDF文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下吧
    2022-03-03

最新評(píng)論

米易县| 阿拉善左旗| 蓝田县| 宣化县| 温州市| 龙南县| 久治县| 仪陇县| 绿春县| 凤山县| 德格县| 万山特区| 黔南| 文安县| 静乐县| 邯郸县| 米易县| 阳江市| 城口县| 陆川县| 贵州省| 乌海市| 阳西县| 丹巴县| 双鸭山市| 靖安县| 邯郸县| 封丘县| 盐山县| 扎囊县| 道孚县| 巫溪县| 宁乡县| 保康县| 改则县| 乡城县| 宜兰县| 会东县| 荥阳市| 新河县| 布拖县|