5-Bean的循环依赖问题

一、Sigle+Set模式的 循环依赖问题。

  • 只有 socle 为 single 才有这个曝光的机制。

image-20230105232610981

-

XML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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="husbandBean" class="com.jhfuture.spring6.Husband" scope="singleton">
<property name="name" value="张三">

</property>
<property name="wife" ref="wifeBean"/>
</bean>
<bean id="wifeBean" class="com.jhfuture.spring6.Wife" scope="singleton">
<property name="name" value="梨花"/>
<property name="husband" ref="husbandBean"></property>
</bean>
</beans>

java src

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

Husband
package com.jhfuture.spring6;

public class Husband {
private String name;
private Wife wife;

public void setName(String name) {
this.name = name;
}

public void setWife(Wife wife) {
this.wife = wife;
}

public String getName() {
return name;
}

@Override
public String toString() {
return "Husband{" +
"name='" + name + '\'' +
", wife=" + wife.getName() +
'}';
}
}


Wife

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.jhfuture.spring6;

public class Wife {
private String name;
private Husband husband;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setHusband(Husband husband) {
this.husband = husband;
}

@Override
public String toString() {
return "Wife{" +
"name='" + name + '\'' +
", husband=" + husband.getName() +
'}';
}
}

二、prototype +Set 模式 —>报错

直接报错

1
2
3
4
5
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'husbandBean' defined in class path resource [circle.xml]: Cannot resolve reference to bean 'wifeBean' while setting bean property 'wife'




XML文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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="husbandBean" class="com.jhfuture.spring6.Husband" scope="prototype">
<property name="name" value="张三">

</property>
<property name="wife" ref="wifeBean"/>
</bean>
<bean id="wifeBean" class="com.jhfuture.spring6.Wife" scope="prototype">
<property name="name" value="梨花"/>
<property name="husband" ref="husbandBean"></property>
</bean>
</beans>

三、single + prototype +Set模式 —>无问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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="husbandBean" class="com.jhfuture.spring6.Husband" scope="prototype">
<property name="name" value="张三">

</property>
<property name="wife" ref="wifeBean"/>
</bean>
<bean id="wifeBean" class="com.jhfuture.spring6.Wife" scope="single">
<property name="name" value="梨花"/>
<property name="husband" ref="husbandBean"></property>
</bean>
</beans>

五、基于构造依赖下产生的循环依赖—–>无法解决

总结 Spring解决循环依赖的机理

核心–>三层缓存

Spring为什么可以解决set + singleton模式下循环依赖?

根本的原因在于:这种方式可以做到将“实例化Bean”和“给Bean属性赋值”这两个动作分开去完成。

实例化Bean的时候:调用无参数构造方法来完成。此时可以先不给属性赋值,可以提前将该Bean对象==“曝光”==给外界。

给Bean属性赋值的时候:调用setter方法来完成。

两个步骤是完全可以分离开去完成的,并且这==两步不要求在同一个时间点上完成==。

也就是说,Bean都是单例的,我们可以先把所有的单例Bean实例化出来,放到一个集合当中(我们可以称之为缓存),所有的单例Bean全部实例化完成之后,以后我们再慢慢的调用setter方法给属性赋值。这样就解决了循环依赖的问题。