詳解Spring Bean的循環(huán)依賴解決方案
如果使用構造函數(shù)注入,則可能會創(chuàng)建一個無法解析的循環(huán)依賴場景。
什么是循環(huán)依賴
循環(huán)依賴其實就是循環(huán)引用,也就是兩個或則兩個以上的bean互相持有對方,最終形成閉環(huán)。比如A依賴于B,B依賴于C,C又依賴于A。如下圖:
注意,這里不是函數(shù)的循環(huán)調(diào)用,是對象的相互依賴關系。循環(huán)調(diào)用其實就是一個死循環(huán),除非有終結(jié)條件。
Spring中循環(huán)依賴場景有:
(1)構造器的循環(huán)依賴
(2)field屬性的循環(huán)依賴。
怎么檢測是否存在循環(huán)依賴
檢測循環(huán)依賴相對比較容易,Bean在創(chuàng)建的時候可以給該Bean打標,如果遞歸調(diào)用回來發(fā)現(xiàn)正在創(chuàng)建中的話,即說明了循環(huán)依賴了。
下面是我所遇到的情況,代碼結(jié)構如下:
SpringSecurity 配置類:
@Configuration public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsService userDetailsService; /** * 通過配置類構造函數(shù)注入 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()); /** * 通過構造函數(shù)注入 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 通過構造函數(shù)注入 UserDetailsService實例,而 UserDetailsService由通過構造函數(shù)注入在BrowserSecurityConfig 中聲明的PasswordEncoder。
總結(jié)來說,Spring Bean的循環(huán)依賴是指,類A需要通過構造函數(shù)注入的類B的實例(或者B中聲明的Bean),而類B需要通過構造函數(shù)注入的類A的實例(或者A中聲明的Bean)。如果將類A和類B的bean配置為相互注入,則Spring IoC容器會在運行時檢測到此循環(huán)引用,并引發(fā)一個BeanCurrentlyInCreationException。與典型情況(沒有循環(huán)依賴)不同,bean A和bean B之間的循環(huán)依賴關系迫使其中一個bean在被完全初始化之前被注入到另一個bean中(這是一個典型的“先有雞還是先有蛋”場景)。
解決方案
簡明扼要的說,就是——不使用基于構造函數(shù)的依賴注入??赏ㄟ^下面方式解決。
在字段上使用@Autowired注解,讓Spring決定在合適的時機注入?!就扑]】
用基于setter方法的依賴注射取代基于構造函數(shù)的依賴注入來解決循環(huán)依賴。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
JAVA“無法驗證證書。將不執(zhí)行該應用程序?!碧崾窘鉀Q辦法
這篇文章主要給大家介紹了關于JAVA“無法驗證證書,將不執(zhí)行該應用程序”提示的解決辦法,要解決Java無法驗證證書的問題,可以嘗試下本文的方法,需要的朋友可以參考下2024-03-03spring boot2.0圖片上傳至本地或服務器并配置虛擬路徑的方法
最近寫了關于圖片上傳至本地文件夾或服務器,上傳路徑到數(shù)據(jù)庫,并在上傳時預覽圖片。本文通過實例代碼給大家分享spring boot2.0圖片上傳至本地或服務器并配置虛擬路徑的方法,需要的朋友參考下2018-12-12Java基礎之重載(Overload)與重寫(Override)詳解
這篇文章主要介紹了Java基礎之重載(Overload)與重寫(Override)詳解,文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢操作
Nebula?Graph?是一款開源的、分布式的、易擴展的原生圖數(shù)據(jù)庫,能夠承載包含數(shù)千億個點和數(shù)萬億條邊的超大規(guī)模數(shù)據(jù)集,并且提供毫秒級查詢,這篇文章主要介紹了Nebula?Graph介紹和SpringBoot環(huán)境連接和查詢,需要的朋友可以參考下2022-10-10Springboot集成JSR303參數(shù)校驗的方法實現(xiàn)
這篇文章主要介紹了Springboot集成JSR303參數(shù)校驗的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09圖解Java經(jīng)典算法插入排序的原理與實現(xiàn)
插入排序的算法描述是一種簡單直觀的排序算法。其原理是通過構建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應位置并插入。本文將用Java語言實現(xiàn)插入排序算法并進行可視化,感興趣的可以了解一下2022-09-09