Spring构造器注入产生的循环依赖以及解决办法
一、循环依赖描述
问题描述:Bean A依赖B,Bean B依赖A,这种情况下即为循环依赖,如下:
Bean A --> Bean B --> Bean A
导致问题:当存在循环依赖时,Spring将无法决定先创建哪个bean,这种情况下,Spring将产生异常BeanCurrentlyInCreationException。
二、构造器循环依赖复现
@Component @Slf4j public class E1 { private E2 e2; public E1(E2 e2) { log.info("E2({})", e2); this.e2 = e2; } } @Component @Slf4j public class E2 { private E1 e1; public E2(E1 e1) { log.info("E1({})", e1); this.e1 = e1; } }
启动项目报错:
*************************** APPLICATION FAILED TO START *************************** Description: The dependencies of some of the beans in the application context form a cycle: ┌─────┐ | e1 defined in file [F:\StudyProject\example-springboot-demo\springboot-demo\target\classes\com\zhixi\config\E1.class] ↑ ↓ | e2 defined in file [F:\StudyProject\example-springboot-demo\springboot-demo\target\classes\com\zhixi\config\E2.class] └─────┘
三、如何解决构造器循环依赖
1、@Lazy注解
对E2进行延迟加载:
@Component @Slf4j public class E1 { private E2 e2; public E1(@Lazy E2 e2) { this.e2 = e2; } } @Component @Slf4j public class E2 { private E1 e1; public E2(E1 e1) { this.e1 = e1; } }
2、使用对象工厂:ObjectFactory
@Component @Slf4j public class E1 { private ObjectFactory<E2> e2; public E1(ObjectFactory<E2> e2) { this.e2 = e2; } } @Component @Slf4j public class E2 { private E1 e1; public E2(E1 e1) { this.e1 = e1; } }
3、使用Provider接口:实质也是一个对象工厂
需要在pom.xml中添加pom:
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
代码如下:
import org.springframework.stereotype.Component; import javax.inject.Provider; @Component public class E1 { private Provider<E2> e2; public E1(Provider<E2> e2) { this.e2 = e2; } } @Component public class E2 { private E1 e1; public E2(E1 e1) { this.e1 = e1; } }