8、Bean的循环依赖问题

1、 singleton下的set注入产生的循环依赖(解决)

A对象中有B属性。B对象中有A属性。这就是循环依赖。我依赖你,你也依赖我。

比如:丈夫类Husband,妻子类WifeHusband中有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);
}

image-20221110211610159

该模式下,为什么循环循环依赖不会出现问题,Spring 是如何对应的

  • 主要原因是,在这中模式下SpringBean 的管理主要分为清晰的两个阶段
    • 第一个阶段:在Spring 容器加载的时候,实例化Bean,只要其中任意一个Bean实例化之后,马上进行" 曝 光 \color{red}曝光 "【不等属性赋值曝光】
    • 第二个阶段:Bean “曝光”之后,在进行属性的赋值
  • 核心解决方案是:实例化对象对象的属性赋值分为两个阶段来完成的
  • 就是 先实例化对象再给对象赋值

注意:

  • 只有在scopesingleton的情况下,Bean才会采取提的“察光的措施。

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

image-20221110214357841

不断的相互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就是了

3、 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对象

注意:

  • 基于构造注入的方式下,产生的循环依赖也是无法解决的,所以编写代码时一定要注意
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值