8.2 singleton下的set注入产生的循环依赖(解决)
A
对象中有B
属性。B
对象中有A
属性。这就是循环依赖。我依赖你,你也依赖我。
比如:丈夫类Husband
,妻子类Wife
。Husband
中有Wife
的引用。Wife
中有Husband
的引用。
Husband
@Data
public class Husband {
private String name;
private Wife wife;
@Override
public String toString() {
return "Husband{" +
"name='" + name + '\'' +
", wife=" + wife.getName() +
'}';
}
}
Wife
@Data
public class Wife {
private String name;
private Husband husband;
@Override
public String toString() {
return "Wife{" +
"name='" + name + '\'' +
", husband=" + husband.getName() +
'}';
}
}
springBean.xml
<!--singleton + setter模式下的循环依赖是没有问题的-->
<!--singleton 表示在整个Spring容器当中是单例的,独一无二的对象。-->
<bean id="husband" class="com.cjf.bean.Husband" scope="singleton">
<property name="name" value="张三"/>
<property name="wife" ref="wife"/>
</bean>
<bean id="wife" class="com.cjf.bean.Wife" scope="singleton">
<property name="name" value="小花"/>
<property name="husband" ref="husband"/>
</bean>
test
@Test
public void testCD() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springBean.xml");
Husband husbandBean = applicationContext.getBean("husband", Husband.class);
Wife wife = applicationContext.getBean("wife", Wife.class);
System.out.println(husbandBean);
System.out.println(wife);
}
该模式下,为什么循环循环依赖不会出现问题,Spring 是如何对应的
- 主要原因是,在这中模式下
Spring
对Bean
的管理主要分为清晰的两个阶段- 第一个阶段:在
Spring
容器加载的时候,实例化Bean
,只要其中任意一个Bean
实例化之后,马上进行" 曝 光 \color{red}曝光 曝光"【不等属性赋值曝光】 - 第二个阶段:
Bean
“曝光”之后,在进行属性的赋值
- 第一个阶段:在
- 核心解决方案是:
实例化对象
和对象的属性赋值
分为两个阶段来完成的 - 就是 先实例化对象再给对象赋值
注意:
- 只有在
scope
是singleton
的情况下,Bean
才会采取提的“察光的措施。
8.3、prototype下的set注入产生的循环依赖
<!--在prototype + setter 模式下的循环依赖,会出现问题异常-->
<bean id="husband" class="com.cjf.bean.Husband" scope="prototype">
<property name="name" value="张三"/>
<property name="wife" ref="wife"/>
</bean>
<bean id="wife" class="com.cjf.bean.Wife" scope="prototype">
<property name="name" value="小花"/>
<property name="husband" ref="husband"/>
</bean>
不断的相互new
新的对象
- 请求的
bean
目前正在创建中:是否有无法解析的循环引用?
若其中一个是singleton
,则不会出现出现问题
<bean id="husband" class="com.cjf.bean.Husband" scope="singleton">
<property name="name" value="张三"/>
<property name="wife" ref="wife"/>
</bean>
<bean id="wife" class="com.cjf.bean.Wife" scope="prototype">
<property name="name" value="小花"/>
<property name="husband" ref="husband"/>
</bean>
因为在husband
创建后,setter
进行赋值wife
。会去创建一个新的wife
对象,在进行husband
赋值,直接获取之前的单例husband
就是了
8.4 singleton下的构造注入产生的循环依赖
<!--构造注入,-->
<bean id="husband" class="com.cjf.bean.Husband" scope="singleton">
<constructor-arg index="0" value="张三"/>
<constructor-arg index="1" ref="wife"/>
</bean>
<bean id="wife" class="com.cjf.bean.Wife" scope="singleton">
<constructor-arg index="0" value="小花"/>
<constructor-arg index="1" ref="husband"/>
</bean>
在husband
创建对象的时候,要给wife
赋值,即去创建wife
对象,wife
对象创建的时候要给husband
赋值,但是husband
未曝光(husband
还在创建过程中),所以wife
对象得不到husband
对象。所以wife
对象也不会被曝光出来,导致husband
对象得不到wife
对象
注意:
- 基于构造注入的方式下,产生的循环依赖也是无法解决的,所以编写代码时一定要注意