Spring循环参考示例

rob*_*bin 26 java spring dependency-injection circular-reference autowired

我在使用spring工作的一个项目中有一个循环引用,我无法修复,并在启动时失败并出现以下错误:

'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
Run Code Online (Sandbox Code Playgroud)

我尝试在示例项目中以较小的级别重新创建相同的问题(没有我的工作项目的所有细节).然而,我无法想出弹簧因错误而失败的合理情况.这就是我所拥有的:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的项目中我有类似的情况,但是失败了,我也期待春天在我的示例项目中抱怨.但它工作正常!有人能给我一个如何用循环引用错误打破弹簧的简单例子吗?

编辑:我使用javax.inject.Provider修复了问题.两个项目中唯一的另一个区别是使用的注释是javax.inject.Inject和javax.annotation.ManagedBean代替@Autowired和@Component.

Fra*_*eth 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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你实现了bean的接口,这将非常有效.


San*_*Lee 26

这是一个老线程,所以我猜你几乎忘记了这个问题,但我想让你知道这个谜.我遇到了同样的问题,我的神奇并没有消失,所以我不得不解决问题.我会一步一步地解决你的问题.

1.为什么你不能重现循环引用异常?

因为Spring会照顾它.它创建bean并根据需要注入它们.

那么为什么你的项目会产生异常呢?

  • 正如@sperumal所说,如果使用构造函数注入,Spring可能会产生循环异常
  • 根据日志,您在项目中使用Spring Security
  • 在Spring Security配置中,它们使用构造函数注入
  • 注入的豆子authenticationManager有圆形参考

那为什么异常会神秘地消失?

异常可能发生也可能不发生取决于bean的创建顺序.我猜你做了几个*context.xml文件,然后用web.xml中的配置加载它们

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:*-context.xml</param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)

xml文件将按XmlWebApplicationContext类加载,并且不保证文件的加载顺序.它只是从文件系统加载文件.问题出在这里.如果类首先加载应用程序上下文文件,则没有问题,因为当用于构造注入Spring Security时,已经创建了bean.但是,如果它首先加载Spring Security上下文文件,则会出现循环引用问题,因为Spring会在创建之前尝试在构造函数注入中使用bean.

4.如何解决问题?

强制xml文件的加载顺序.在我的例子中,我使用安装上下文xml文件在应用程序上下文文件的末尾加载<import resource="">.即使使用相同的代码,也可以根据环境更改加载顺序,因此我建议设置顺序以消除潜在问题.


spe*_*mal 9

根据Spring文档,可以获得循环依赖性问题或BeanCurrentlyInCreationException使用构造函数注入.

解决问题的解决方案是使用setter而不是Constructor注入.

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

  • 我认为你误解了那里写的内容:如果你主要使用构造函数注入,**有可能**创建一个无法解析的循环依赖场景. (2认同)