一、概述
循环依赖是指,多个bean之间相互依赖,形成了一个闭环。比如A依赖于B、B依赖于C、C依赖于A,形成了一个圈。
二、两种方式对循环依赖的影响
2.1、官网说明
2.2、结论
我们AB循环依赖问题只要A的注入方式是setter、并且是singleton,就不会出现循环依赖问题。
三、BeanCurrentlyInCreationException
3.1、构造方法注入
3.1.1、ServiceA
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/10/27 23:27
* @Description:
*/
public class ServiceA {
private ServiceB serviceB;
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
System.out.println("构造方法:A中设置了属性B");
}
}
3.1.2、ServiceB
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/10/27 23:27
* @Description:
*/
public class ServiceB {
private ServiceA serviceA;
public ServiceB(ServiceA serviceA) {
this.serviceA = serviceA;
System.out.println("构造方法:B中设置了属性A");
}
}
3.1.3、xml配置
<!-- 使用构造方法注入属性:会产生循环依赖问题 -->
<bean id="a" class="org.star.component.inject.constructor.ServiceA">
<constructor-arg name="serviceB" ref="b"/>
</bean>
<bean id="b" class="org.star.component.inject.constructor.ServiceB">
<constructor-arg name="serviceA" ref="a"/>
</bean>
3.1.4、测试
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/10/27 23:23
* @Description:
*/
public class SpringCircularDependencyMainApp {
public static void main(String[] args) {
m1();
}
/**
* 使用构造方法注入属性:会产生循环依赖问题
*/
private static void m1() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ServiceA serviceA = context.getBean(ServiceA.class);
System.out.println(serviceA);
}
}
3.1.5、结论
使用构造方法注入属性:会产生循环依赖问题。
3.2、set方法注入
3.2.1、ServiceAA
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/10/27 23:30
* @Description:
*/
public class ServiceAA {
private ServiceBB serviceBB;
public ServiceBB getServiceBB() {
return serviceBB;
}
public void setServiceBB(ServiceBB serviceBB) {
this.serviceBB = serviceBB;
System.out.println("aa里面设置了属性bb");
}
}
3.2.2、ServiceBB
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/10/27 23:30
* @Description:
*/
public class ServiceBB {
private ServiceAA serviceAA;
public ServiceAA getServiceAA() {
return serviceAA;
}
public void setServiceAA(ServiceAA serviceAA) {
this.serviceAA = serviceAA;
System.out.println("bb里面设置了属性aa");
}
}
3.2.3、xml配置
<!-- 使用set方法注入属性:不会产生循环依赖问题 -->
<bean id="aa" class="org.star.component.inject.setter.ServiceAA">
<property name="serviceBB" ref="bb"/>
</bean>
<bean id="bb" class="org.star.component.inject.setter.ServiceBB">
<property name="serviceAA" ref="aa"/>
</bean>
3.2.4、测试
/**
* @Author : 一叶浮萍归大海
* @Date: 2023/10/27 23:23
* @Description:
*/
public class SpringCircularDependencyMainApp {
public static void main(String[] args) {
m2();
}
/**
* 使用set方法注入属性:不会产生循环依赖问题
*/
private static void m2() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ServiceAA aa = context.getBean(ServiceAA.class);
ServiceBB bb = context.getBean(ServiceBB.class);
System.out.println(aa);
System.out.println(bb);
}
}
3.2.5、结论
使用set方法注入属性:不会产生循环依赖问题
3.3、注意事项
默认的单例bean是支持循环依赖的,但是当把scope的值改为prototype时,将会报错。