色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術文章
文章詳情頁

基于SpringBoot構造器注入循環依賴及解決方式

瀏覽:2日期:2023-05-20 16:50:26

1. 循環依賴是什么?

Bean A 依賴 B,Bean B 依賴 A這種情況下出現循環依賴。

Bean A → Bean B → Bean A

更復雜的間接依賴造成的循環依賴如下。

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

2. 循環依賴會產生什么結果?

當Spring正在加載所有Bean時,Spring嘗試以能正常創建Bean的順序去創建Bean。

例如,有如下依賴:

Bean A → Bean B → Bean C

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

但當存在循環依賴時,Spring將無法決定先創建哪個bean。這種情況下,Spring將產生異常BeanCurrentlyInCreationException。

當使用構造器注入時經常會發生循環依賴問題。如果使用其它類型的注入方式能夠避免這種問題。

3. 構造器注入循環依賴實例

首先定義兩個相互通過構造器注入依賴的bean。

@Componentpublic class CircularDependencyA { private CircularDependencyB circB; @Autowired public CircularDependencyA(CircularDependencyB circB) { this.circB = circB; }}

@Componentpublic class CircularDependencyB { private CircularDependencyA circA; @Autowired public CircularDependencyB(CircularDependencyA circA) { this.circA = circA; }}

@Configuration@ComponentScan(basePackages = { 'com.baeldung.circulardependency' })public class TestConfig {}

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = { TestConfig.class })public class CircularDependencyTest { @Test public void givenCircularDependency_whenConstructorInjection_thenItFails() { // Empty test; we just want the context to load }}

運行方法givenCircularDependency_whenConstructorInjection_thenItFails將會產生異常:

BeanCurrentlyInCreationException: Error creating bean with name ‘circularDependencyA’: Requested bean is currently in creation: Is there an unresolvable circular reference?

4.解決方法

處理這種問題目前有如下幾種常見方式。

4.1 重新設計

重新設計結構,消除循環依賴。

4.2 使用注解 @Lazy

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

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

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

4.3 使用Setter/Field注入

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

@Componentpublic class CircularDependencyA { private CircularDependencyB circB; @Autowired public void setCircB(CircularDependencyB circB) { this.circB = circB; } public CircularDependencyB getCircB() { return circB; }}

@Componentpublic class CircularDependencyB { private CircularDependencyA circA; private String message = 'Hi!'; @Autowired public void setCircA(CircularDependencyA circA) { this.circA = circA; } public String getMessage() { return message; }}

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = { TestConfig.class })public class CircularDependencyTest { @Autowired ApplicationContext context; @Bean public CircularDependencyA getCircularDependencyA() { return new CircularDependencyA(); } @Bean public CircularDependencyB getCircularDependencyB() { return new CircularDependencyB(); } @Test public void givenCircularDependency_whenSetterInjection_thenItWorks() { CircularDependencyA circA = context.getBean(CircularDependencyA.class); Assert.assertEquals('Hi!', circA.getCircB().getMessage()); }}

4.4 使用@PostConstruct

@Componentpublic class CircularDependencyA { @Autowired private CircularDependencyB circB; @PostConstruct public void init() { circB.setCircA(this); } public CircularDependencyB getCircB() { return circB; }}

@Componentpublic class CircularDependencyB { private CircularDependencyA circA; private String message = 'Hi!'; public void setCircA(CircularDependencyA circA) { this.circA = circA; } public String getMessage() { return message; }

4.5 實現ApplicationContextAware與InitializingBean

@Componentpublic 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; }}

@Componentpublic class CircularDependencyB { private CircularDependencyA circA; private String message = 'Hi!'; @Autowired public void setCircA(CircularDependencyA circA) { this.circA = circA; } public String getMessage() { return message; }}

5.總結

處理循環依賴有多種方式。首先考慮是否能夠通過重新設計依賴來避免循環依賴。如果確實需要循環依賴,那么可以通過前文提到的方式來處理。優先建議使用setter注入來解決。

以上這篇基于SpringBoot構造器注入循環依賴及解決方式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持好吧啦網。

標簽: Spring
相關文章:
主站蜘蛛池模板: 日韩午夜视频在线观看 | 精品视频在线免费播放 | 亚洲综合无码一区二区 | 亚洲精品欧美精品 | 亚洲成a人片在线观看精品 亚洲成a人片在线观看中 | 国产精品成人亚洲 | 国产精品久久免费观看 | pgone太大了兽王免费视频 | 国产边打电话边做对白刺激 | 日本人视频网站一 | 国产成人精品福利网站在线观看 | 国产17部性孕妇孕交在线 | 国产一级爱c片免费播放 | 欧美日本韩国一区 | 怡红院在线视频全部观看 | 日韩视频免费一区二区三区 | 国产成人精品免费视频大全软件 | 欧美久久久久久久一区二区三区 | 免费人成在线观看网站视频 | 日韩精品一区二区三区四区 | 国产精品二区三区免费播放心 | 欧美透逼视频 | 成人一区二区免费中文字幕 | 国产精品亚洲一区在线播放 | 国产盗摄精品一区二区三区 | 欧美久久久久久久久 | 亚洲日韩aⅴ在线视频 | 国产精品私人玩物在线观看 | 国产精品久久久久无码av | 九九色视频在线观看 | 国产精品青草久久 | 国产成人一区二区三区精品久久 | 国产做a爰片久久毛片 | 欧美日韩免费做爰视频 | 日韩精品亚洲专区在线观看 | 欧美高清视频手机在在线 | 免费永久国产在线视频 | 538在线视频二三区视视频 | 亚洲欧美日韩久久一区 | 在线亚洲成人 | 亚洲精品国产一区二区三区在 |