1:問題
最近啟動項目時候,遇到如下報錯
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'stockReceiptManager': Bean with name 'stockReceiptManager' has been injected
the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
?
2:分析原因
后來在網上找了半天說是依賴循環,檢查了一下代碼,確實存在循環依賴的現象
spring默認是支持循環依賴,allowCircularRefrence默認為true。也可以手動設置applicationContext.setAllowCircularReferences(false); 產生這個問題原因:in its raw version as part of a circular reference, but has eventually been wrapped.應該是項目中對某個類的方法開啟異步@Async導致
?
3:解釋循環依賴
首先說一下什么是依賴循環,比如:我現在有一個ServiceA需要調用ServiceB的方法,那么ServiceA就依賴于ServiceB,那在ServiceB中再調用ServiceA的方法,就形成了循環依賴。Spring在初始化bean的時候就不知道先初始化哪個bean就會報錯。
由于類A通過構造注入需要類B的實例,而類B通過構造注入需要類B的實例,二者之間相互注入,導致循環引用拋出異常,這是一個典型的先有雞還是先有蛋的故事。所以在使用spring配置類的循環依賴的關系時,應當盡量避免使用構造注入,而是使用setter注入。
public class ClassA {@AutowiredClassB classB;
}public class ClassB {@AutowiredClassA classA ;
}
?
那如何解決循環依賴,當然最好的方法是重構你的代碼,進行解耦,但是重構不是一時的事情,那就使用下面的方法:
方法一:
<bean id="ServiceDependent1" class="org.xyz.ServiceDependent1" lazy-init="true"><constructor-arg ref="Service"/>
</bean><bean id="ServiceDependent2" class="org.xyz.ServiceDependent2" lazy-init="true"><constructor-arg ref="Service"/>
</bean>
?
方法二:
在你的配置文件中,在互相依賴的兩個bean的任意一個加上lazy-init屬性。
在你注入bean時,在互相依賴的兩個bean上加上@Lazy注解也可以。
以上兩種方法都能延遲互相依賴的其中一個bean的加載,從而解決循環依賴的問題。
@Autowired@Lazyprivate ClassA classA;@Autowired@Lazyprivate ClassB classB;
?