當使用構造器注入時經常發生循環依賴問題,因此本篇將重點闡述如何解決該問題:
1 循環依賴
問題描述:Bean A依賴B,Bean B依賴A,這種情況下即為循環依賴,如下:
Bean A --> Bean B --> Bean A
導致問題:當存在循環依賴時,Spring將無法決定先創建哪個bean,這種情況下,Spring將產生異常BeanCurrentlyInCreationException。
2 問題復現
定義如下兩個Component:
@Component public class E1 { private E2 e2; public E1(E2 e2) { this.e2 = e2; } } @Component public class E2 { private E1 e1; public E2(E1 e1) { this.e1 = e1; } }
當啟動SpringBoot應用時就會報循環依賴問題,如下所示:
3 解決方案
方式一:延遲構造
消除循環依賴的方式是通過延遲加載,只需要在任意一個中使用@Lazy即可解決,如下:
@Component
public class E1 { private E2 e2; public E1(@Lazy E2 e2) { this.e2 = e2; } } @Component public class E2 { private E1 e1; public E2(E1 e1) { this.e1 = e1; } }
方式二:使用setter注入
當依賴最終被使用時再進行注入是最佳的一種方式,同時這也是Spring最推薦的一種方式,如下:
@Component public class E1 { private E2 e2; public void setE2(E2 e2) { this.e2 = e2; } } @Component public class E2 { private E1 e1; public void setE1(E1 e1) { this.e1 = e1; } }
這里需要說明的是:處理循環依賴有很多種方式。我們在處理循環依賴時,首先應該考慮的是是否能夠通過重新設計依賴來避免循環依賴並且我們能否接受因重新設計導致的時間成本。如果成本很高或者我們確實需要循環依賴,那么可以使用本文提到的方式來解決循環依賴問題,並且推薦優先考慮使用setter方式。