springboot-springboot2.1.x報錯循環依賴問題

前言
實際開發中,咱們經常是基於模塊分工開發的,也就是不一樣的人負責不一樣的模塊。最後合併代碼。這種方式適合多人協同,每一個人只關心本身的業務模塊實現(controller/model/service/mapper等),當碰到須要其它模塊支持的功能時,只需引入其它模塊的類便可調用其方法html

循環依賴問題
Bean A 依賴 B,Bean B 依賴 A這種狀況下出現循環依賴。
Bean A → Bean B → Bean Aapp

更復雜的間接依賴形成的循環依賴以下。
Bean A → Bean B → Bean C → Bean D → Bean E → Bean Athis

循環依賴問題的本質
當程序啓動,Spring Context加載全部的Bean時,會嘗試按他們運行的工做順序建立Bean。.net

例如,有以下依賴:
Bean A → Bean B → Bean C
Spring先建立beanC,接着建立bean B(將C注入B中),最後建立bean A(將B注入A中)。設計

但當存在循環依賴時,Spring將沒法決定先建立哪一個bean。這種狀況下,Spring將產生異常BeanCurrentlyInCreationException。代理

舉例
有一個ServiceA須要調用ServiceB的方法,那麼ServiceA就依賴於ServiceB,那在ServiceB中再調用ServiceA的方法,就造成了循環依賴。Spring在初始化bean的時候就不知道先初始化哪一個,bean就會報錯。code

解決
從新設計
從新設計結構,消除循環依賴。htm

使用註解 @Lazy
一種最簡單的消除循環依賴的方式是經過延遲加載。在注入依賴時,先注入代理對象,當首次使用時再建立對象完成注入。
 對象

@Autowired
	@Lazy
	private ServiceA serviceA;

	@Autowired
	@Lazy
	private ServiceB serviceB;

使用Setter/Field注入
Spring文檔建議的一種方式是使用setter注入。當依賴最終被使用時才進行注入。blog

@Component
public class ServiceA {
    private ServiceB serviceB;
    @Autowired
    public void setServiceB(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
    public ServiceB getServiceB() {
        return serviceB;
    }
}

使用@PostConstruct

@Component
public class ServiceA {

    @Autowired
    private ServiceB serviceB;
 
    @PostConstruct
    public void init() {
        serviceB.setServiceA(this);
    }
 
    public ServiceB getServiceB() {
        return serviceB;
    }
}

1.淺談Spring解決循環依賴的三種方式

2.SpringBoot2.1.x報錯循環依賴問題解決方法

3.SpringBoot構造器注入循環依賴及解決

相關文章
相關標籤/搜索