Spring中解決循環依賴報錯的問題


什么是循環依賴

當一個ClassA依賴於ClassB,然后ClassB又反過來依賴ClassA,這就形成了一個循環依賴:

ClassA -> ClassB -> ClassA

原創聲明

本文發布於掘金號【Happyjava】。Happy的掘金地址:https://juejin.im/user/5cc2895df265da03a630ddca,Happy的個人博客:(http://blog.happyjava.cn)[http://blog.happyjava.cn]。歡迎轉載,但須保留此段聲明。

Spring的循環依賴問題

當你使用構造注入依賴的時候,就有可能發生循環依賴然后報錯的問題。什么是構造注入呢?可以看如下代碼:

假設有ClassA和ClassB如下:

ClassA.java

@Data
@Component
public class ClassA {

    private final ClassB classB;

    public ClassA(ClassB classB) {
        this.classB = classB;
    }
}

ClassB.java

@Data
@Component
public class ClassB {

    private final ClassA classA;

    public ClassB(ClassA classA) {
        this.classA = classA;
    }
}

就是在類的構造方法里,把依賴注入,這就是所說的構造注入。

構造注入,也是Spring團隊推薦的Spring依賴注入的方式(依賴來自IDEA的提示):

雖然是Spring的官方推薦,但是這種方式就是容易出現循環依賴導致程序跑不起來的情況:

當然,也存在多種解決循環依賴的辦法,下面一一演示。

重新設計代碼

當出現循環依賴的時候,可以考慮重新設計下代碼。一般來說,當循環依賴問題出現的時候,往往其原因是設計上分層沒有處理好,各個類的耦合度高,各自的職責不夠單一。

當然,很多時候,我們也沒有那么多時間去重新設計代碼。那么,我們可以采取別的方式。

使用懶加載

可以通過Spring提供的@Lazy注解,讓Spring懶加載,即當真正需要使用到該bean的時候,再去加載。如,我給上面的示例代碼的ClassB的構造方法加入@Lazy注解:

@Data
@Component
public class ClassB {

    private final ClassA classA;

    public ClassB(@Lazy ClassA classA) {
        this.classA = classA;
    }
}

再次啟動,就會發現循環依賴報錯問題不存在了。

直接使用Autowired單獨注入

直接使用@Autowired注入依賴,不要使用構造器的方式注入

@Data
@Component
public class ClassB {

    @Autowired
    private ClassA classA;

}
@Data
@Component
public class ClassA {

    @Autowired
    private ClassB classB;

}

這種方式,也可以解決Spring循環依賴的問題。

使用Setter注入

除了以上兩種方式,還可以通過setter的方式來注入依賴。如下:

ClassA.class

@Data
@Component
public class ClassA {

    private ClassB classB;

    @Autowired
    public void setClassB(ClassB classB) {
        this.classB = classB;
    }
}

ClassB.class

@Data
@Component
public class ClassB {

    private ClassA classA;

    @Autowired
    public void setClassA(ClassA classA) {
        this.classA = classA;
    }
}

通過Setter注入依賴的方式,一樣可以解決Spring循環依賴的問題。

總結

使用Spring作為開發框架,一不小心就會碰到循環依賴,程序啟動不了的問題。如果真的出現了循環依賴的問題,可以嘗試采用上面的幾種方式解決。當然,解決的辦法還有很多,比如,還可以通過PostConstruct注解來解決(摘抄baeldung的博客):

方法可能有很多種,就不太深入探討了。

關注公眾號領資料

搜索公眾號【Happyjava】,回復【電子書】和【視頻】,即可獲取大量優質電子書和大數據、kafka、nginx、MySQL等視頻資料

關注Happyjava公眾號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM