关于Sping框架中循环依赖的问题及解决方法

什么是循环依赖?

在学习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);
	}
}

结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值