您的位置:首页 > 编程语言 > Java开发

Spring如何解决循环依赖

2014-03-10 21:36 746 查看
Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类:

public class TestA {

private TestB testB;

public void a() {
testB.b();
}

public TestB getTestB() {
return testB;
}

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

public class TestB {
private TestC testC;

public void b() {
testC.c();
}

public TestC getTestC() {
return testC;
}

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

public class TestC {
private TestA testA;

public void c() {
testA.a();
}

public TestA getTestA() {
return testA;
}

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


在Spring中将循环依赖的处理分成了3种情况。

1.构造器循环依赖

表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyIn CreationException异常表示循环依赖。

如在创建TestA类时,构造器需要TestB类,那将去创建TestB,在创建TestB类时又发现需要TestC类,则又去创建TestC,最终在创建TestC时发现又需要TestA,从而形成一个环,没办法创建。

Spring容器将每一个正在创建的bean标识符放在一个"当前创建bean池"中,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建bean过程中发现自己已经在"当前创建bean池"里时,将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的bean将从"当前创建bean池"中清除掉。

我们通过一个直观的测试用例来进行分析。

(1)创建配置文件。

<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>


(2)创建测试用例。

@Test(expected = BeanCurrentlyInCreationException.class)
public void testCircleByConstructor() throws Throwable {
try {
new ClassPathXmlApplicationContext("test.xml");
} catch (Exception e) {
//因为要在创建testC时抛出;
Throwable ee1 = e.getCause().getCause().getCause();
throw e1;
}
}Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?首先让我们来定义循环引用类:public class TestA {

private TestB testB;

public void a() {
testB.b();
}

public TestB getTestB() {
return testB;
}

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

public class TestB {
private TestC testC;

public void b() {
testC.c();
}

public TestC getTestC() {
return testC;
}

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

public class TestC {
private TestA testA;

public void c() {
testA.a();
}

public TestA getTestA() {
return testA;
}

public void setTestA(TestA testA) {
this.testA = testA;
}
}
在Spring中将循环依赖的处理分成了3种情况。1.构造器循环依赖表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyIn CreationException异常表示循环依赖。如在创建TestA类时,构造器需要TestB类,那将去创建TestB,在创建TestB类时又发现需要TestC类,则又去创建TestC,最终在创建TestC时发现又需要TestA,从而形成一个环,没办法创建。Spring容器将每一个正在创建的bean标识符放在一个"当前创建bean池"中,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建bean过程中发现自己已经在"当前创建bean池"里时,将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的bean将从"当前创建bean池"中清除掉。我们通过一个直观的测试用例来进行分析。(1)创建配置文件。
<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>
(2)创建测试用例。
@Test(expected = BeanCurrentlyInCreationException.class)
public void testCircleByConstructor() throws Throwable {
try {
new ClassPathXmlApplicationContext("test.xml");
} catch (Exception e) {
//因为要在创建testC时抛出;
Throwable ee1 = e.getCause().getCause().getCause();
throw e1;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: