spring循环依赖 —— 《Spring源码深度解析》

什么是循环依赖?

定义:循环依赖是指两个或者两个以上的bean相互持有对方,比如:Spring在调用类A的构造函数初始化的时候,A依赖B,这时就需要先去初始化B,初始化B的时候,B又依赖C,所以就又去初始化C,初始化C的时候需要A,这就构成了一种循环依赖。

先定义循环引用的类:

public class TestA {
	// TestA依赖TestB
	private TestB testB;
	
	public TestA(TestB testB) {
		this.testB = testB;
	}
	
	public TestB getTestB() {
		return testB;
	}

	public void setTestB() {
		this.testB = testB;
	}
}

public class TestB {
	// TestB依赖TestC
	private TestC testC;
	
	public TestB(TestC testC) {
		this.testC = testC;
	}
	
	public TestC getTestC() {
		return testC;
	}

	public void setTestC() {
		this.testC = testC;
	}
}

public class TestC {
	// TestC依赖TestA
	private TestA testA;
	
	public TestC(TestA testA) {
		this.testA = testA;
	}
	
	public TestA getTestA() {
		return testA;
	}

	public void setTestA() {
		this.testA = testA;
	}
}

有哪些循环依赖?

构造器循环依赖

定义:在通过构造器注入的时候产生的循环依赖,示例如下:

<bean id="testA" class="com.bean.TestA">
	<constructor-arg index="0" ref="testB" />
</bean>
<bean id="testB" class="com.bean.TestB">
	<constructor-arg index="0" ref="testC" />
</bean>
<bean id="testC" class="com.bean.TestC">
	<constructor-arg index="0" ref="testA" />
</bean>
setter循环依赖

定义:在通过setter方式注入的时候产生的循环依赖,示例如下:

<bean id="testA" class="com.bean.TestA">
	<property name="testB" ref="testB" />
</bean>
<bean id="testB" class="com.bean.TestB">
	<property name="testC" ref="testC" />
</bean>
<bean id="testC" class="com.bean.TestC">
	<property name="testA" ref="testA" />
</bean>

如何解决这些循环依赖?

Spring对循环依赖的处理分成了三种情况:
构造器循环依赖的处理
> 此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常来终止该依赖。 具体的处理步骤: 1.Spring将每个正在创建的bean的标识符放在一个池子里 2.如果bean在创建的时候发现自己已经存在于这个池子里 3.则抛出异常,中断循环依赖
setter循环依赖的处理
> 解决方案: 1.spring将已经完成了构造注入但是未完成setter注入的bean暴露出来 2.当进行setter注入时,发现这个需被注入的bean已经被暴露出来(**存在该bean的引用**),直接注入即可,而不需要再次加载所需的bean。
prototype(多例)范围的依赖处理
> 对于多例的bean,Spring无法完成依赖注入,因为spring容器不缓存“prototype”作用域的bean,因此无法提前暴露一个创建中的bean,但是对于单例(singleton)的bean,可以通过“setAllowCircularReferences( false );”来禁用循环引用。

总结:综上所述,只有单例作用域的setter注入可以解决,其他的都无法解决,都得通过抛出BeanCurrentlyInCreationException异常来解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值