24

我在工作中的一個項目有一個循環引用使用Spring,對此我無法修復,並失敗,出現以下錯誤啓動:春圓形參考示例

'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference? 

我試着在示例項目的較小級別重新創建相同的問題(沒有我的工作項目的所有細節)。然而,我一直無法想出一個合理的情況,即春天失敗並出現錯誤。 這是我有:

public class ClassA { 
    @Autowired 
    ClassB classB; 
} 

public class ClassB { 
    @Autowired 
    ClassC classC; 
} 

@Component 
public class ClassC { 
    @Autowired 
    ClassA classA; 
} 

@Configuration 
public class Config { 
    @Bean 
    public ClassA classA() { 
     return new ClassA(); 
    } 

    @Bean 
    public ClassB classB() { 
     return new ClassB(); 
    } 
} 

我有一個類似的場景在我的項目,該項目失敗,我期待春天在我的樣本項目,抱怨也是如此。但它工作正常!有人能給我一個簡單的例子,說明如何用循環引用錯誤來破解彈簧嗎?

編輯:我使用javax.inject.Provider固定的問題。 2個項目中唯一的另一個區別是使用的註釋是javax.inject.Inject和javax.annotation.ManagedBean來代替@Autowired和@Component。

回答

23

這是一個古老的線程,所以我想你幾乎忘了這個問題,但我想讓你知道這個謎。我遇到了同樣的問題,而且我的魔法並沒有消失,所以我必須解決問題。我會一步一步解決你的問題。

1.爲什麼不能重現循環引用異常?

因爲Spring takes care of it. It creates beans and injects them as required

2.那麼爲什麼你的項目會產生異常?

  • 作爲@sperumal說,如果你使用構造器注入
  • 根據日誌彈簧可產生圓形異常,你使用Spring Security在你的項目
  • 在春季安全配置,他們確實使用構造函數注射
  • 你豆類中注入了authenticationManager有循環引用

3,那爲什麼有恩ception走神祕?

可能發生或可能不發生的異常取決於bean的創建順序。我猜你做幾個*context.xml文件左右,並在web.xml

<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>classpath:*-context.xml</param-value> 
</context-param> 

XmlWebApplicationContext類文件的加載順序加載XML文件中,不能保證與配置類似下面加載它們。它只是從文件系統加載文件。問題在這裏。如果類首先加載應用程序上下文文件沒有問題,因爲您的bean在用於Spring Security的構造注入時已經創建。但是,如果它首先加載Spring Security上下文文件,則會出現循環引用問題,因爲Spring在創建之前會嘗試在構造函數注入中使用bean。

4.如何解決問題?

強制xml文件的加載順序。就我而言,我使用<import resource="">在應用程序上下文文件的末尾加載了安全上下文xml文件。即使使用相同的代碼,加載順序也可以根據環境進行更改,所以我建議設置順序以消除潛在的問題。

26

你可以使用@Lazy,表明bean被延後創建,打破自動裝配的渴望循環。

這個想法是循環中的一些bean可以被實例化爲一個代理,並且只是在真正需要時它會被初始化。這意味着,所有的bean都被初始化,除了代理之外。第一次使用它將觸發配置,而其他bean已經配置,這不會成爲問題。

從Spring的吉拉一個問題:可在結合使用@Configuration ,表明該配置類中的所有豆類應 延遲初始化

@Lazy註解。當然,@Lazy也可以結合使用 與單獨的@Bean方法來指示一個接一個地基於 的延遲初始化。 https://jira.springsource.org/browse/SJC-263

意思是說你的註釋bean作爲@Lazy就足夠了。或者如果你喜歡只是註釋配置類爲@Lazy如下:

@Configuration 
@Lazy 
public class Config { 
    @Bean 
    public ClassA classA() { 
     return new ClassA(); 
    } 

    @Bean 
    public ClassB classB() { 
     return new ClassB(); 
    } 
} 

如果您實現您的豆這會工作得很好的接口。

+1

只是爲了增加這一點,我們遇到了類似的問題(注入SpringTemplateEngine)。 「setter注入」解決方案沒有幫助,但「@ Lazy」註解做到了。這感覺就像一個彈傷創傷的創可貼,但現在我會取勝並走開。謝謝Spaeth先生。 – demaniak 2016-02-08 15:33:59

9

根據Spring文檔,可以通過使用構造函數注入來獲得循環依賴性問題或BeanCurrentlyInCreationException

解決此問題的解決方案是使用setter而不是構造函數注入。

參考http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html

+2

我想你誤解了那裏寫的東西:如果你主要使用構造函數注入,**可能會創建一個無法解析的循環依賴方案。 – 2012-07-05 16:58:35

+1

構造函數注入優於setter注入 - 在構造函數調用完成之前,您的bean不存在,而使用setter注入時,您可能省略了一些必要的參數,並且bean在未正確配置的狀態下存在一段時間 – 2012-07-05 18:21:28