我在使用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解决了这个问题。两个项目中唯一的另一个区别是使用的注释是javax.inject.Inject和javax.annotation.ManagedBean代替@Autowired和@Component。
答案 0 :(得分:26)
您可以使用@Lazy
来表示该bean是懒惰创建的,从而打破了自动装配的热切周期。
这个想法是循环中的某些bean可以被实例化为代理,并且就在它真正需要的时候它将被初始化。这意味着,除了作为代理的bean之外,所有bean都被初始化。首次使用它将触发配置,并且由于已经配置了其他bean,因此不会出现问题。
来自Spring-Jira的一个问题:
@Lazy注释,可以与@Configuration一起使用 表示该配置类中的所有bean都应该是 懒洋洋地初始化。当然,@ 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();
}
}
如果你实现了bean的接口,这将非常有用。
答案 1 :(得分:26)
这是一个老线程,所以我猜你几乎忘了这个问题,但我想让你知道这个谜。我遇到了同样的问题,我的神奇并没有消失,所以我必须解决这个问题。我会一步一步地解决你的问题。
<强> 1。为什么你无法重现循环引用异常?
因为Spring takes care of it. It creates beans and injects them as required。
<强> 2。那么为什么你的项目会产生异常呢?
authenticationManager
的bean具有循环引用第3。那为什么异常会神秘地消失呢?
异常可能发生也可能不发生取决于bean的创建顺序。我猜你做了几个*context.xml
个文件,然后在web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:*-context.xml</param-value>
</context-param>
xml文件将由XmlWebApplicationContext
类加载,并且不保证文件的加载顺序。它只是从文件系统加载文件。问题出在这里。如果类首先加载应用程序上下文文件,则没有问题,因为当bean用于Spring Security的构造注入时已经创建了bean。但是,如果它首先加载Spring Security上下文文件,则会出现循环引用问题,因为Spring会在创建之前尝试在构造函数注入中使用bean。
<强> 4。如何解决问题?
强制xml文件的加载顺序。在我的例子中,我使用<import resource="">
在应用程序上下文文件的末尾加载了安全上下文xml文件。即使使用相同的代码,也可以根据环境更改加载顺序,因此我建议您设置顺序以消除潜在的问题。
答案 2 :(得分:9)
根据Spring文档,可以通过使用构造函数注入来获取循环依赖性问题或BeanCurrentlyInCreationException
。
解决问题的方法是使用setter而不是Constructor injection。
参考http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html。
答案 3 :(得分:2)