Spring中的循环依赖
Posted Beginner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中的循环依赖相关的知识,希望对你有一定的参考价值。
循环依赖
在使用Spring时,如果主要采用基于构造器
的依赖注入方式,则可能会遇到循环依赖的情况,简而言之就是Bean A
的构造器依赖于Bean B
,Bean B
的构造器又依赖于Bean A
。在这种情况下Spring会在编译时抛出BeanCurrentlyInCreationException
。
Class A
@Component
public class ClassA {
private ClassB classB;
@Autowired
public ClassA(ClassB classB) {
this.classB = classB;
}
public void printClass() {
System.out.println("Class A = " + this);
System.out.println("Class B = " + classB);
}
}
Class B
@Component
public class ClassB {
private ClassA classA;
@Autowired
public ClassB(ClassA classA) {
this.classA = classA;
}
public void printClass() {
System.out.println("Class A = " + classA);
System.out.println("Class B = " + this);
}
}
测试
@ContextConfiguration(classes = {ClassA.class, ClassB.class})
@RunWith(SpringRunner.class)
public class MyTest {
@Autowired
private ClassA classA;
@Autowired
private ClassB classB;
@Test
public void name() {
classA.printClass();
classB.printClass();
}
}
原因
这时候运行测试就会发现抛出了BeanCurrentlyInCreationException
异常。产生这种情况的原因是,Spring在创建Bean时,会首先实例化对象,然后再注入依赖。假设Spring首先创建Class A
,那么就会发现在构造器里有Class B
的依赖,所以就会转去创建Class B
,又在Class B
的构造器里发现了对Class A
的依赖,而此时Class A
是还未初始化完的,因此又会转去创建Class A
,这样就陷入了死循环。
解决方法
换成基于setter
的依赖注入即可解决这个问题。因为基于setter
的依赖注入会首先调用默认构造函数来实例化对象,然后再调用setter
实现依赖注入。这样在对象实例化的阶段就没有了任何依赖,因此Class A
实例化完成后再调用Class B
,Class B
实例化完成后开始设值,而这时Class A
已经是实例化完成了的,所以可以成功引用到Class A
。
以上是关于Spring中的循环依赖的主要内容,如果未能解决你的问题,请参考以下文章
spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段