1:写在前面
这里的循环依赖指的是基于引用的依赖,而非depend-on或者是其他。当A引用B,B引用C,C又引用A就构成了循环引用,也就是我们平时所说的循环依赖了,这里也有不同的情况,bean为单例的,bean为原型的,基于属性构成的循环依赖,基于构造函数参数构成的循环依赖,我们来分别看下这些情况。
2:单例基于属性的循环依赖
2.1:定义3个类
public class SingletonByPropertyA {
private SingletonByPropertyB singletonByPropertyB;
public SingletonByPropertyB getSingletonByPropertyB() {
return singletonByPropertyB;
}
public void setSingletonByPropertyB(SingletonByPropertyB singletonByPropertyB) {
this.singletonByPropertyB = singletonByPropertyB;
}
}
public class SingletonByPropertyB {
private SingletonByPropertyC singletonByPropertyC;
public SingletonByPropertyC getSingletonByPropertyC() {
return singletonByPropertyC;
}
public void setSingletonByPropertyC(SingletonByPropertyC singletonByPropertyC) {
this.singletonByPropertyC = singletonByPropertyC;
}
}
public class SingletonByPropertyC {
private SingletonByPropertyA singletonByPropertyA;
public SingletonByPropertyA getSingletonByPropertyA() {
return singletonByPropertyA;
}
public void setSingletonByPropertyA(SingletonByPropertyA singletonByPropertyA) {
this.singletonByPropertyA = singletonByPropertyA;
}
}
可以看到SingletonByPropertyA引用SingletonByPropertyB,SingletonByPropertyB引用SingletonByPropertyC,SingletonByPropertyC引用SingletonByPropertyA,就构成了循环依赖了。
2.2:定义配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="byPropertyA" class="yudaosourcecode.recyclereference.SingletonByPropertyA">
<property name="singletonByPropertyB" ref="byPropertyB"/>
</bean>
<bean id="byPropertyB" class="yudaosourcecode.recyclereference.SingletonByPropertyB">
<property name="singletonByPropertyC" ref="byPropertyC"/>
</bean>
<bean id="byPropertyC" class="yudaosourcecode.recyclereference.SingletonByPropertyC">
<property name="singletonByPropertyA" ref="byPropertyA"/>
</bean>
</beans>
2.3:测试
代码:
@Test
public void testrecyclereference_singleton_field() {
ClassPathXmlApplicationContext ac
= new ClassPathXmlApplicationContext("testrecyclereference_singleton_field.xml");
System.out.println(ac.getBean("byPropertyA"));
System.out.println(ac.getBean("byPropertyB"));
System.out.println(ac.getBean("byPropertyC"));
}
运行:
yudaosourcecode.recyclereference.SingletonByPropertyA@7a30d1e6
yudaosourcecode.recyclereference.SingletonByPropertyB@5891e32e
yudaosourcecode.recyclereference.SingletonByPropertyC@cb0ed20
Process finished with exit code 0
3:单例基于构造函数参数的循环依赖
3.1:定义3个类
public class SingletonConstructorArgA {
public SingletonConstructorArgA(SingletonConstructorArgB singletonConstructorArgB) {}
}
public class SingletonConstructorArgB {
public SingletonConstructorArgB(SingletonConstructorArgC singletonConstructorArgC) {}
}
public class SingletonConstructorArgC {
public SingletonConstructorArgC(SingletonConstructorArgA singletonConstructorArgA) {}
}
3.2:定义配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="singletonConstructorArgA" class="yudaosourcecode.recyclereference.SingletonConstructorArgA">
<constructor-arg index="0" ref="singletonConstructorArgB"/>
</bean>
<bean id="singletonConstructorArgB" class="yudaosourcecode.recyclereference.SingletonConstructorArgB">
<constructor-arg index="0" ref="singletonConstructorArgC"/>
</bean>
<bean id="singletonConstructorArgC" class="yudaosourcecode.recyclereference.SingletonConstructorArgC">
<constructor-arg index="0" ref="singletonConstructorArgA"/>
</bean>
</beans>
3.3:测试
@Test
public void testrecyclereference_singleton_constructorarg() {
new ClassPathXmlApplicationContext("testrecyclereference_singleton_constructorarg.xml");
}
运行:
...
Error creating bean with name 'singletonConstructorArgA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
可以看到因为循环引用依赖报错了,所以可以得出结论,对于单例的由于构造函数参数的引用造成的循环依赖spring不解决,而是直接异常。
4:原型基于属性的循环依赖
4.1:定义3个类
public class PrototypeByPropertyA {
private PrototypeByPropertyB prototypeByPropertyB;
public PrototypeByPropertyB getPrototypeByPropertyB() {
return prototypeByPropertyB;
}
public void setPrototypeByPropertyB(PrototypeByPropertyB prototypeByPropertyB) {
this.prototypeByPropertyB = prototypeByPropertyB;
}
}
public class PrototypeByPropertyB {
private PrototypeByPropertyC prototypeByPropertyC;
public PrototypeByPropertyC getPrototypeByPropertyC() {
return prototypeByPropertyC;
}
public void setPrototypeByPropertyC(PrototypeByPropertyC prototypeByPropertyC) {
this.prototypeByPropertyC = prototypeByPropertyC;
}
}
public class PrototypeByPropertyC {
private PrototypeByPropertyA prototypeByPropertyA;
public PrototypeByPropertyA getPrototypeByPropertyA() {
return prototypeByPropertyA;
}
public void setPrototypeByPropertyA(PrototypeByPropertyA prototypeByPropertyA) {
this.prototypeByPropertyA = prototypeByPropertyA;
}
}
4.2:定义配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="prototypeByPropertyA" class="yudaosourcecode.recyclereference.PrototypeByPropertyA" scope="prototype">
<property name="prototypeByPropertyB" ref="prototypeByPropertyB"/>
</bean>
<bean id="prototypeByPropertyB" class="yudaosourcecode.recyclereference.PrototypeByPropertyB" scope="prototype">
<property name="prototypeByPropertyC" ref="prototypeByPropertyC"/>
</bean>
<bean id="prototypeByPropertyC" class="yudaosourcecode.recyclereference.PrototypeByPropertyC" scope="prototype">
<property name="prototypeByPropertyA" ref="prototypeByPropertyA"/>
</bean>
</beans>
4.3:测试
@Test
public void testrecyclereference_prototype_field() {
ClassPathXmlApplicationContext ac
= new ClassPathXmlApplicationContext("testrecyclereference_prototype_field.xml");
System.out.println(ac.getBean("prototypeByPropertyA"));
System.out.println(ac.getBean("prototypeByPropertyB"));
System.out.println(ac.getBean("prototypeByPropertyC"));
}
运行:
...
exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'prototypeByPropertyA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
可以看到报了循环依赖的错误,可以得出结论,对于原型方式的属性引用构成的循环依赖,spring不处理,直接异常。
5:原型基于构造函数的循环依赖
5.1:定义3个类
public class PrototypeByConstructorArgA {
public PrototypeByConstructorArgA(PrototypeByConstructorArgB prototypeByConstructorArgB) {}
}
public class PrototypeByConstructorArgB {
public PrototypeByConstructorArgB(PrototypeByConstructorArgC prototypeByConstructorArgC) {}
}
public class PrototypeByConstructorArgC {
public PrototypeByConstructorArgC(PrototypeByConstructorArgA prototypeByConstructorArgA) {}
}
5.2:定义配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="prototypeByConstructorArgA" class="yudaosourcecode.recyclereference.PrototypeByConstructorArgA" scope="prototype">
<constructor-arg name="prototypeByConstructorArgB" ref="prototypeByConstructorArgB"/>
</bean>
<bean id="prototypeByConstructorArgB" class="yudaosourcecode.recyclereference.PrototypeByConstructorArgB" scope="prototype">
<constructor-arg name="prototypeByConstructorArgC" ref="prototypeByConstructorArgC"/>
</bean>
<bean id="prototypeByConstructorArgC" class="yudaosourcecode.recyclereference.PrototypeByConstructorArgC" scope="prototype">
<constructor-arg name="prototypeByConstructorArgA" ref="prototypeByConstructorArgA"/>
</bean>
</beans>
5.3:测试
@Test
public void testrecyclereference_prototype_construstorarg() {
ClassPathXmlApplicationContext ac
= new ClassPathXmlApplicationContext("testrecyclereference_prototype_construstorarg.xml");
System.out.println(ac.getBean("prototypeByConstructorArgA"));
System.out.println(ac.getBean("prototypeByConstructorArgB"));
System.out.println(ac.getBean("prototypeByConstructorArgC"));
}
运行:
...snip...
[testrecyclereference_prototype_construstorarg.xml]:
Cannot resolve reference to bean 'prototypeByConstructorArgA' while setting constructor argument;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'prototypeByConstructorArgA':
Requested bean is currently in creation: Is there an unresolvable circular reference?
可以看到提示了循环依赖的错误,可以得出结论,对于原型bean基于构造函数引用的循环依赖spring是不处理的,直接异常。