系列十九、循环依赖(一)
一、概述
循环依赖是指,多个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时,将会报错。