什么是循环依赖?
在学习Spring框架时,会学习到关于IOC(Inversion of Control)控制反转这块内容时,需要将一些对象的创建交给Spring容器管理。这时如果不小心就会遇到循环依赖的问题。
循环依赖具体是指在A对象中引用了B对象,B对象又引用了A对象,而且A和B都交给了Spring容器进行管理。如下代码所示:
1 属性注入的方式(不会有循环依赖的问题)
package com.itheima.circulate1;
/**
* 属性注入的方式演示循环引用
* @author WL20180723
* @date 2021年2月21日上午11:07:06
*
*/
public class Cat1 {
private Dog1 dog1;
public Dog1 getDog1() {
return dog1;
}
public void setDog1(Dog1 dog1) {
this.dog1 = dog1;
}
}
package com.itheima.circulate1;
/**
* 属性注入的方式演示循环引用
* @author WL20180723
* @date 2021年2月21日上午11:06:52
*
*/
public class Dog1 {
private Cat1 cat1;
public Cat1 getCat1() {
return cat1;
}
public void setCat1(Cat1 cat1) {
this.cat1 = cat1;
}
}
Spring配置文件bean1.xml:
<?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="dog1" class="com.itheima.circulate1.Dog1">
<property name="cat1" ref="cat1"></property>
</bean>
<bean id="cat1" class="com.itheima.circulate1.Cat1">
<property name="dog1" ref="dog1"></property>
</bean>
</beans>
上例中就是A和B相互引用然后交给Spring容器进行管理,测试如下:
package com.itheima.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.circulate1.Cat1;
import com.itheima.circulate1.Dog1;
/**
* 测试循环依赖
* @author WL20180723
* @date 2021年2月21日下午3:56:52
*
*/
public class TestCirculateReference {
//属性注入
@Test
public void test1() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Dog1 dog1 = context.getBean(Dog1.class);
System.out.println("==========属性注入==========");
System.out.println("Dog1:" + dog1);
Cat1 cat1 = context.getBean(Cat1.class);
System.out.println("Cat1:" + cat1);
}
}
结果如下:
==========属性注入==========
Dog1:com.itheima.circulate1.Dog1@e874448
Cat1:com.itheima.circulate1.Cat1@29b5cd00
上例中虽然是A和B相互引用,似乎会引起循环依赖的问题,但是由于使用了属性注入的方式,Spring框架自动处理了这种问题,所以没有出现循环依赖的问题。但是如果使用构造方法注入的方式就会引发循环的问题!!!
2 构造方法注入的方式(引发循环依赖问题)
package com.itheima.circulate2;
/**
*
* @author WL20180723
* @date 2021年2月21日上午11:36:54
*
*/
public class Cat2 {
private Dog2 dog2;
public Cat2(Dog2 dog2) {
this.dog2 = dog2;
}
}
package com.itheima.circulate2;
/**
*
* @author WL20180723
* @date 2021年2月21日上午11:37:00
*
*/
public class Dog2 {
private Cat2 cat2;
public Dog2(Cat2 cat2) {
this.cat2 = cat2;
}
}
Spring配置文件bean2.xml:
<?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="dog2" class="com.itheima.circulate2.Dog2">
<constructor-arg index="0" ref="cat2"></constructor-arg>
</bean>
<bean id="cat2" class="com.itheima.circulate2.Cat2">
<constructor-arg index="0" ref="dog2"></constructor-arg>
</bean>
</beans>
测试代码及结果如下:
package com.itheima.test;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.circulate1.Cat1;
import com.itheima.circulate1.Dog1;
/**
* 测试循环依赖
* @author WL20180723
* @date 2021年2月21日下午3:56:52
*
*/
public class TestCirculateReference {
//构造方法注入
@Test
public void test2() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
Dog1 dog1 = context.getBean(Dog1.class);
System.out.println("==========构造方法注入==========");
System.out.println("Dog1:" + dog1);
Cat1 cat1 = context.getBean(Cat1.class);
System.out.println("Cat1:" + cat1);
}
}
结果如下: