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

SpringBoot構(gòu)造器注入循環(huán)依賴及解決方案

 更新時間:2024年03月27日 11:35:22   作者:不懂原理的程序員.  
這篇文章主要介紹了SpringBoot構(gòu)造器注入循環(huán)依賴及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

SpringBoot構(gòu)造器注入循環(huán)依賴及解決

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

Bean A 依賴 B,Bean B 依賴 A這種情況下出現(xiàn)循環(huán)依賴。

Bean A → Bean B → Bean A

更復(fù)雜的間接依賴造成的循環(huán)依賴如下。

Bean A → Bean B → Bean C → Bean D → Bean E → Bean A

(解釋一下,三個以上其實和兩個是一樣的,多加幾個@lazy就可以了,等到后面bean創(chuàng)建成功再創(chuàng)建)

2. 循環(huán)依賴會產(chǎn)生什么結(jié)果?

當(dāng)Spring正在加載所有Bean時,Spring嘗試以能正常創(chuàng)建Bean的順序去創(chuàng)建Bean。

例如,有如下依賴:

Bean A → Bean B → Bean C

Spring先創(chuàng)建beanC,接著創(chuàng)建bean B(將C注入B中),最后創(chuàng)建bean A(將B注入A中)。

但當(dāng)存在循環(huán)依賴時,Spring將無法決定先創(chuàng)建哪個bean。這種情況下,Spring將產(chǎn)生異常BeanCurrentlyInCreationException。

當(dāng)使用構(gòu)造器注入時經(jīng)常會發(fā)生循環(huán)依賴問題。如果使用其它類型的注入方式能夠避免這種問題。

簡單構(gòu)造器注入循環(huán)依賴實例

項目結(jié)構(gòu)

如下:

1.首先定義兩個相互通過構(gòu)造器注入依賴的bean。

/**
 * @Author: lixs
 * @Date: 2021/4/6
 * @Description: 循環(huán)依賴類A
 */
@Component
public class CircularDependencyA {


    private CircularDependencyB circB;

    @Autowired
    public CircularDependencyA(@Lazy CircularDependencyB circB) {
        this.circB = circB;
    }
}
/**
 1. @Author: lixs
 2. @Date: 2021/4/6
 3. @Description: 循環(huán)依賴類B
 */
@Component
public class CircularDependencyB {

    private CircularDependencyA circA;

    @Autowired
    public CircularDependencyB(@Lazy CircularDependencyA circA) {
        this.circA= circA;
    }
}

2.創(chuàng)建配置類

/**
 1. @Author: lixs
 2. @Date: 2021/4/6
 3. @Description: 配置類
 */
@Configuration
@ComponentScan(basePackages = { "com.li.springboot.bean" })
public class TestConfig {
}

3.創(chuàng)建測試類

@SpringBootTest
@ContextConfiguration(classes = {TestConfig.class})
class ApplicationTests {

    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        // Empty test; we just want the context to load
    }
}

正常運行結(jié)果:

上面就是報的是循環(huán) 依賴無法創(chuàng)建bean錯誤!

解決方案

1.重新設(shè)計

重新設(shè)計結(jié)構(gòu),不用這種方式去創(chuàng)建bean。

2.使用注解 @Lazy

一種最簡單的消除循環(huán)依賴的方式是通過延遲加載。

在注入依賴時,先注入代理對象,當(dāng)首次使用時再創(chuàng)建對象完成注入。

/**
 * @Author: lixs
 * @Date: 2021/4/6
 * @Description: 循環(huán)依賴類A
 */
@Component
public class CircularDependencyA {

    private CircularDependencyB circB;

    @Autowired
    public CircularDependencyA(@Lazy CircularDependencyB circB) {
        this.circB = circB;
    }
}

使用@Lazy后,運行代碼,可以看到異常消除。

3.使用Setter/Field注入

Spring文檔建議的一種方式是使用setter注入。當(dāng)依賴最終被使用時才進行注入。對前文的樣例代碼少做修改,來觀察測試效果。

@Component
public class CircularDependencyA {
 
    private CircularDependencyB circB;
 
    @Autowired
    public void setCircB(CircularDependencyB circB) {
        this.circB = circB;
    }
 
    public CircularDependencyB getCircB() {
        return circB;
    }
}
@Component
public class CircularDependencyB {
 
    private CircularDependencyA circA;
 
    private String message = "Hi!";
 
    @Autowired
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
 
    public String getMessage() {
        return message;
    }
}

測試類

@SpringBootTest
@ContextConfiguration(classes = {TestConfig.class})
class ApplicationTests {

     @Autowired
    ApplicationContext context;    //spring容器對象
 
    @Bean
    public CircularDependencyA getCircularDependencyA() {
        return new CircularDependencyA();
    }
 
    @Bean
    public CircularDependencyB getCircularDependencyB() {
        return new CircularDependencyB();
    }
 
    @Test
    public void testCircularDependency() {
    	//拿到bean對象
        CircularDependencyA circA = context.getBean(CircularDependencyA.class);
        //獲取屬性值
        String result=circA.getCircB().getMessage();
        System.out.println(result);
    }

4.使用@PostConstruct

@PostContruct是spring框架的注解,在方法上加該注解會在項目啟動的時候執(zhí)行該方法,也可以理解為在spring容器初始化的時候執(zhí)行該方法。

@Component
public class CircularDependencyA {
 
    @Autowired
    private CircularDependencyB circB;
 
    @PostConstruct
    public void init() {
        circB.setCircA(this);
    }
 
    public CircularDependencyB getCircB() {
        return circB;
    }
}
public class CircularDependencyB {
 
    private CircularDependencyA circA;
     
    private String message = "Hi!";
 
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
     
    public String getMessage() {
        return message;
    }
}

5.實現(xiàn)ApplicationContextAware與InitializingBean

(1)如果某個類實現(xiàn)了ApplicationContextAware接口,會在類初始化完成后調(diào)用setApplicationContext()方法進行操作

(2)如果某個類實現(xiàn)了InitializingBean接口,會在類初始化完成后,并在setApplicationContext()方法執(zhí)行完畢后,調(diào)用afterPropertiesSet()方法進行操作

@Component
public class CircularDependencyA implements ApplicationContextAware, InitializingBean {
 
    private CircularDependencyB circB;
 
    private ApplicationContext context;
 
    public CircularDependencyB getCircB() {
        return circB;
    }
 
    @Override
    public void afterPropertiesSet() throws Exception {
        circB = context.getBean(CircularDependencyB.class);
    }
 
    @Override
    public void setApplicationContext(final ApplicationContext ctx) throws BeansException {
        context = ctx;
    }
}
@Component
public class CircularDependencyB {
 
    private CircularDependencyA circA;
 
    private String message = "Hi!";
 
    @Autowired
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
 
    public String getMessage() {
        return message;
    }
}

總結(jié)

處理循環(huán)依賴有多種方式。

首先考慮是否能夠通過重新設(shè)計依賴來避免循環(huán)依賴。

如果確實需要循環(huán)依賴,那么可以通過前文提到的方式來處理。

優(yōu)先建議使用setter注入來解決。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot整合mybatis的方法詳解

    SpringBoot整合mybatis的方法詳解

    這篇文章主要為大家詳細介紹了SpringBoot整合mybatis的方法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 使用java生成json時產(chǎn)生棧溢出錯誤問題及解決方案

    使用java生成json時產(chǎn)生棧溢出錯誤問題及解決方案

    這篇文章主要介紹了使用java生成json時產(chǎn)生棧溢出錯誤問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • SpringBoot從2.7.x 升級到3.3注意事項

    SpringBoot從2.7.x 升級到3.3注意事項

    從SpringBoot 2.7.x升級到3.3涉及多個重要變更,特別是因為 Spring Boot 3.x 系列基于 Jakarta EE 9,而不再使用 Java EE,本文就來詳細的介紹一下,感興趣的可以了解一下
    2024-09-09
  • Spring?boot?啟動流程及外部化配置方法

    Spring?boot?啟動流程及外部化配置方法

    平時我們開發(fā)Spring boot 項目的時候,一個SpringBootApplication注解加一個main方法就可以啟動服務(wù)器運行起來,那它到底是怎么運行起來的呢?這篇文章主要介紹了Spring?boot?啟動流程及外部化配置,需要的朋友可以參考下
    2022-12-12
  • idea中database不顯示問題的解決

    idea中database不顯示問題的解決

    這篇文章主要介紹了idea中database不顯示問題的解決,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 三種簡單排序算法(使用java實現(xiàn))

    三種簡單排序算法(使用java實現(xiàn))

    下面小編就為大家?guī)硪黄N簡單排序算法(使用java實現(xiàn))。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • Java springboot 整合 Nacos的實例代碼

    Java springboot 整合 Nacos的實例代碼

    這篇文章主要介紹了Java springboot 整合 Nacos的實例,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • springboot聚合工程的部署與深入講解

    springboot聚合工程的部署與深入講解

    最近在寫一個商城,使用Maven聚合工程來管理,但是其中搭建環(huán)境遇見了各種的坑,下面這篇文章主要給大家介紹了關(guān)于springboot聚合工程部署的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • 16 個有用的的Java工具類(小結(jié))

    16 個有用的的Java工具類(小結(jié))

    這篇文章主要介紹了16 個有用的的Java工具類,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Java并發(fā)編程同步器CountDownLatch

    Java并發(fā)編程同步器CountDownLatch

    這篇文章主要介紹了Java并發(fā)編程同步器CountDownLatch,文章基于Java并發(fā)編程的相關(guān)資料展開具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04

最新評論