什么是循环依赖
一个Bean A 依赖于 Bean B 同时 Bean B 依赖于Bean A;
也有可能是更加复杂的循环依赖:
Bean A → Bean B → Bean C → Bean D → Bean E → Bean A
Spring中发生了什么
当Spring上下文加载所有bean时,它会尝试按照它们完全工作所需的顺序创建bean。
如果我们没有循环依赖:Bean A → Bean B → Bean C
Spring将创建bean C,然后创建bean B(并将bean C 注入其中),然后创建bean A(并将bean B注入其中)。
但是,当具有循环依赖时,Spring无法决定应该首先创建哪个bean,因为它们彼此依赖。
在这些情况下,Spring将在加载上下文时引发BeanCurrentlyInCreationException。
使用构造函数注入时,这种循环依赖的问题可能在Spring中发生;
如果您使用其他类型的注入,则不应该发现此问题,因为依赖项将在需要时注入,而不是在上下文加载时注入。
解决方案
重新设计
如果您有循环依赖关系,则可能是您遇到了设计问题而且责任分离不清。
您应该尝试正确地重新设计组件,以便它们的层次结构设计得很好,并且不需要循环依赖。
如果您无法重新设计组件(可能有许多可能的原因:遗留代码,已经过测试且无法修改的代码,没有足够的时间或资源来完成重新设计……),有一些可行的解决方法。
使用@Lazy
打破循环的一个简单方法是让Spring懒加载初始化其中一个bean。
那就是:它不是完全初始化bean,而是创建一个代理将它注入另一个bean。
注入的bean只有在第一次需要时才会完全创建。