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

Spring解決循環(huán)依賴問題的四種方法匯總

 更新時(shí)間:2024年07月21日 13:58:35   作者:jc0803kevin  
這篇文章主要介紹了Spring解決循環(huán)依賴問題的四種方法匯總,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

Spring解決循環(huán)依賴問題的四種方法

  • @Lazy方式
  • 使用Setter/Field Injection
  • 使用@PostConstruct
  • 實(shí)現(xiàn) ApplicationContextAware 和 InitializingBean

不管使用那種方式,最佳的還是通過調(diào)整代碼結(jié)構(gòu),從根上設(shè)計(jì)從而達(dá)到避免。

定義兩個(gè)相互依賴的 bean(通過構(gòu)造函數(shù)注入)

package icu.kevin.springpart.circular.constructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyA {
    private CircularDependencyB circB;
    @Autowired
    public CircularDependencyA(CircularDependencyB circB) {
        this.circB = circB;
    }
}
package icu.kevin.springpart.circular.constructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyB {
    private CircularDependencyA circA;
    @Autowired
    public CircularDependencyB(CircularDependencyA circA) {
        this.circA = circA;
    }
}
package icu.kevin.springpart.circular.constructor;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = { "icu.kevin.springpart.circular.constructor" })
public class TestConfig {
}

編寫測試用例,測試是否存在循環(huán)依賴

package icu.kevin.springpart.circular.constructor;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyIntegrationTest {
    // Error creating bean with name 'circularDependencyA': Requested bean is currently in creation: Is there an unresolvable circular reference?
    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        // 測試可以為空,因?yàn)樵谏舷挛募虞d期間將檢測到循環(huán)依賴關(guān)系
    }
}

@Lazy方式

@Lazy告訴 Spring 延遲初始化其中一個(gè) bean。因此,它不會(huì)完全初始化 Bean,而是創(chuàng)建一個(gè)代理將其注入另一個(gè) Bean。注入的 Bean 只有在第一次需要時(shí)才會(huì)完全創(chuàng)建。

@Lazy 注解是通過建立一個(gè)中間代理層,來破解循環(huán)依賴的。

package icu.kevin.springpart.circular.lazy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyA {
    private CircularDependencyB circB;
    @Autowired
    public CircularDependencyA(@Lazy CircularDependencyB circB) {
        this.circB = circB;
    }
}
package icu.kevin.springpart.circular.lazy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyB {
    private CircularDependencyA circA;
    @Autowired
    public CircularDependencyB(CircularDependencyA circA) {
        this.circA = circA;
    }
}
package icu.kevin.springpart.circular.lazy;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = { "icu.kevin.springpart.circular.lazy" })
public class TestConfig {
}
package icu.kevin.springpart.circular.lazy;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyIntegrationTest {
    // Error creating bean with name 'circularDependencyA': Requested bean is currently in creation: Is there an unresolvable circular reference?
    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        // 測試可以為空,因?yàn)樵谏舷挛募虞d期間將檢測到循環(huán)依賴關(guān)系
    }
}

啟動(dòng)可以看出,在上下文檢查循環(huán)依賴是可以正常通過的

查看源碼ContextAnnotationAutowireCandidateResolver#getLazyResolutionProxyIfNecessary首先會(huì)調(diào)用 isLazy 去判斷一下是否需要延遲加載,
如果需要,則調(diào)用 buildLazyResolutionProxy 方法構(gòu)建一個(gè)延遲加載的對(duì)象;

使用Setter/Field Injection

在setter注入的時(shí)候發(fā)生的依賴循環(huán)是可以被解決的,但只能解決單例情況的循環(huán)依賴。
對(duì)于setter注入造成的依賴是通過Spring容器提前暴露剛剛完成構(gòu)造器但還沒有進(jìn)行注入的bean來完成的。通過提前暴露一個(gè)單例工廠讓其他的bean可以引用到該Bean。

package icu.kevin.springpart.circular.setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyA {
    private CircularDependencyB circB;
    public CircularDependencyB getCircB() {
        return circB;
    }
    @Autowired
    public void setCircB(CircularDependencyB circB) {
        this.circB = circB;
    }
}
package icu.kevin.springpart.circular.setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyB {
    private CircularDependencyA circA;
    private String message = "Hi!";
    public CircularDependencyA getCircA() {
        return circA;
    }
    @Autowired
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
package icu.kevin.springpart.circular.setter;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = { "icu.kevin.springpart.circular.setter" })
public class TestConfig {
}
package icu.kevin.springpart.circular.setter;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyIntegrationTest {
    @Autowired
    private ApplicationContext context;
    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        // Empty test; we just want the context to load
        CircularDependencyA circA = context.getBean(CircularDependencyA.class);
        Assert.assertEquals("Hi!", circA.getCircB().getMessage());
    }
}

使用@PostConstruct

package icu.kevin.springpart.circular.postConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class CircularDependencyA {
    @Autowired
    private CircularDependencyB circB;
    @PostConstruct
    public void init(){
        circB.setCircA(this);
    }
    public CircularDependencyB getCircB() {
        return circB;
    }
}
package icu.kevin.springpart.circular.postConstruct;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyB {
    private CircularDependencyA circA;
    private String message = "Hi!";
    public CircularDependencyA getCircA() {
        return circA;
    }
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
package icu.kevin.springpart.circular.postConstruct;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = { "icu.kevin.springpart.circular.postConstruct" })
public class TestConfig {
}
package icu.kevin.springpart.circular.postConstruct;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyIntegrationTest {
    @Autowired
    private ApplicationContext context;
    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        //
        CircularDependencyA circA = context.getBean(CircularDependencyA.class);
        Assert.assertEquals("Hi!", circA.getCircB().getMessage());
    }
}

實(shí)現(xiàn) ApplicationContextAware 和 InitializingBean

如果其中一個(gè) Bean 實(shí)現(xiàn)了 ApplicationContextAware,則該 Bean 可以訪問 Spring 上下文,并可以從那里提取另一個(gè) Bean。

通過實(shí)現(xiàn) InitializingBean,我們指示該 Bean 在設(shè)置完所有屬性后必須執(zhí)行一些操作。在這種情況下,我們要手動(dòng)設(shè)置依賴項(xiàng)。

package icu.kevin.springpart.circular.initializingBean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@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;
    }
}
package icu.kevin.springpart.circular.initializingBean;
import org.springframework.stereotype.Component;
@Component
public class CircularDependencyB {
    private CircularDependencyA circA;
    private String message = "Hi!";
    public CircularDependencyA getCircA() {
        return circA;
    }
    public void setCircA(CircularDependencyA circA) {
        this.circA = circA;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}
package icu.kevin.springpart.circular.initializingBean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = { "icu.kevin.springpart.circular.initializingBean" })
public class TestConfig {
}
package icu.kevin.springpart.circular.initializingBean;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
public class CircularDependencyIntegrationTest {
    @Autowired
    private ApplicationContext context;
    @Test
    public void givenCircularDependency_whenConstructorInjection_thenItFails() {
        // Empty test; we just want the context to load
        CircularDependencyA circA = context.getBean(CircularDependencyA.class);
        Assert.assertEquals("Hi!", circA.getCircB().getMessage());
    }
}

到此這篇關(guān)于Spring解決循環(huán)依賴問題的四種方法的文章就介紹到這了,更多相關(guān)Spring循環(huán)依賴內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 分模塊構(gòu)建Maven工程的方法步驟

    分模塊構(gòu)建Maven工程的方法步驟

    這篇文章主要介紹了分模塊構(gòu)建Maven工程的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • java進(jìn)行遠(yuǎn)程部署與調(diào)試及原理詳解

    java進(jìn)行遠(yuǎn)程部署與調(diào)試及原理詳解

    這篇文章主要介紹了java進(jìn)行遠(yuǎn)程部署與調(diào)試及原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Java實(shí)現(xiàn)添加,讀取和刪除Excel圖片的方法詳解

    Java實(shí)現(xiàn)添加,讀取和刪除Excel圖片的方法詳解

    本文介紹在Java程序中如何添加圖片到excel表格,以及如何讀取、刪除excel表格中已有的圖片。文中的示例代碼講解詳細(xì),感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • 解決springboot文件上傳提示臨時(shí)文件夾不存在問題

    解決springboot文件上傳提示臨時(shí)文件夾不存在問題

    這篇文章主要介紹了解決springboot文件上傳提示臨時(shí)文件夾不存在問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Java中Iterator與ListIterator迭代的區(qū)別

    Java中Iterator與ListIterator迭代的區(qū)別

    本文主要介紹了Java中Iterator與ListIterator迭代的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • SpringBoot?2.7.18?集成?Mybatis?Plus?+?Druid的實(shí)例詳解

    SpringBoot?2.7.18?集成?Mybatis?Plus?+?Druid的實(shí)例詳解

    Mybatis和MybatisPlus都是流行的持久層框架,MybatisPlus在Mybatis基礎(chǔ)上增加了更多便捷的功能,如自動(dòng)CRUD、分頁插件等,文章還提到了Entity、Mapper、Service、Controller等組件的基本使用方法,為開發(fā)者提供了一套完整的集成方案
    2024-10-10
  • java中HashMap的七種遍歷方式小結(jié)

    java中HashMap的七種遍歷方式小結(jié)

    本文主要介紹了java中HashMap的七種遍歷方式小結(jié),包括迭代器,For Each,Lambda,Streams API等,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • 關(guān)于使用jpa聚合函數(shù)遇到的問題

    關(guān)于使用jpa聚合函數(shù)遇到的問題

    這篇文章主要介紹了關(guān)于使用jpa聚合函數(shù)遇到的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Springboot2集成pagehelper過程圖解

    Springboot2集成pagehelper過程圖解

    這篇文章主要介紹了springboot2集成pagehelper過程圖解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • 解決for循環(huán)為空不需要判斷的問題

    解決for循環(huán)為空不需要判斷的問題

    這篇文章主要介紹了解決for循環(huán)為空不需要判斷的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09

最新評(píng)論