溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳解Spring Bean的循環依賴解決方案

發布時間:2020-10-04 21:31:37 來源:腳本之家 閱讀:307 作者:盲枸 欄目:編程語言

如果使用構造函數注入,則可能會創建一個無法解析的循環依賴場景。

什么是循環依賴

循環依賴其實就是循環引用,也就是兩個或則兩個以上的bean互相持有對方,最終形成閉環。比如A依賴于B,B依賴于C,C又依賴于A。如下圖:

詳解Spring Bean的循環依賴解決方案

注意,這里不是函數的循環調用,是對象的相互依賴關系。循環調用其實就是一個死循環,除非有終結條件。

Spring中循環依賴場景有:

(1)構造器的循環依賴
(2)field屬性的循環依賴。

怎么檢測是否存在循環依賴

檢測循環依賴相對比較容易,Bean在創建的時候可以給該Bean打標,如果遞歸調用回來發現正在創建中的話,即說明了循環依賴了。

下面是我所遇到的情況,代碼結構如下:

SpringSecurity 配置類:

@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
  private final UserDetailsService userDetailsService;

  /**
   * 通過配置類構造函數注入 UserDetailsService
   */  
  @Autowired
  public BrowserSecurityConfig(UserDetailsService userDetailsService) {
    this.userDetailsService = userDetailsService;
  }

  /**
   * 在配置類中聲明 加密編碼器
   */
  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  ... ...
}

UserDetailsService 類:

@Component
public class MyUserDetailService implements UserDetailsService {
  private final PasswordEncoder passwordEncoder;

  private Logger logger = LoggerFactory.getLogger(getClass());

  /**
   * 通過構造函數注入 PasswordEncoder 
   */  
  @Autowired
  public MyUserDetailService(PasswordEncoder passwordEncoder) {
    this.passwordEncoder = passwordEncoder;
  }
  ... ...
}

運行之后,Spring拋出了如下錯誤信息:

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  browserSecurityConfig defined in file [D:\CODE\Java\IdeaProjects\mango-security\mango-security-browser\target\classes\stu\mango\security\browser\BrowserSecurityConfig.class]
↑     ↓
|  myUserDetailService defined in file [D:\CODE\Java\IdeaProjects\mango-security\mango-security-browser\target\classes\stu\mango\security\browser\MyUserDetailService.class]
└─────┘

該例中,BrowserSecurityConfig 通過構造函數注入 UserDetailsService實例,而 UserDetailsService由通過構造函數注入在BrowserSecurityConfig 中聲明的PasswordEncoder。

總結來說,Spring Bean的循環依賴是指,類A需要通過構造函數注入的類B的實例(或者B中聲明的Bean),而類B需要通過構造函數注入的類A的實例(或者A中聲明的Bean)。如果將類A和類B的bean配置為相互注入,則Spring IoC容器會在運行時檢測到此循環引用,并引發一個BeanCurrentlyInCreationException。與典型情況(沒有循環依賴)不同,bean A和bean B之間的循環依賴關系迫使其中一個bean在被完全初始化之前被注入到另一個bean中(這是一個典型的“先有雞還是先有蛋”場景)。

解決方案

簡明扼要的說,就是——不使用基于構造函數的依賴注入??赏ㄟ^下面方式解決。

在字段上使用@Autowired注解,讓Spring決定在合適的時機注入?!就扑]】

用基于setter方法的依賴注射取代基于構造函數的依賴注入來解決循環依賴。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女