Spring之IOC循环依赖问题

本文详细探讨了Spring框架中循环依赖的原理,包括构造器和Field属性的依赖场景,以及Spring如何通过缓存机制在singleton bean中巧妙避免循环。实例解析了原型bean和singleton bean的区别处理策略。
摘要由CSDN通过智能技术生成

Spring IOC循环依赖问题

1. 什么是循环依赖

循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环。⽐如A依赖于B,B又依赖于A。套娃模式无限循环。这⾥不是函数的循环调⽤,是对象的相互依赖关系。循环调⽤其实就是⼀个死循环,除⾮有终结条件。

image-20210327173647881

2. Spring中循环依赖场景有哪些

1. 构造器的循环依赖(构造器注⼊)

2. Field 属性的循环依赖(set注⼊)

3. Spring是如何处理循环依赖的

1. 构造器的循环依赖无法解决

​ 因为构造器要调用构造函数new 一个对象出来,而参数又依赖于另一个对象。创建类A依赖于类B,new 的时候去创建类B发现类B不存在就会出错拋出 BeanCurrentlyInCreationException 异常。

2. prototype 原型bean循环依赖⽆法解决

对于原型bean的初始化过程中不论是通过构造器参数循环依赖还是通过setXxx⽅法产⽣循环依赖,Spring都 会直接报错处理。

if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}


protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>)
curVal).contains(beanName))));
}

在获取bean之前如果这个原型bean正在被创建则直接抛出异常。原型bean在创建之前会进⾏标记这个beanName正在被创建,等创建结束之后会删除标记

try {
//创建原型bean之前添加标记
beforePrototypeCreation(beanName);
//创建原型bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
//创建原型bean之后删除标记
afterPrototypeCreation(beanName);
}
3. singleton bean 可以通过三级缓存的方式解决循环依赖
  1. 类A开始调用set方法注入类B,在缓存池中找不到类B,就把类A放到三级缓存池singletonFactorys,转而开始创建类B。
  2. 创建类B发现要set方法注入类A,在一级缓存容器中singletonObjects发现类A不存在,继续找,发现在三级缓存池中有半成品的类A的对象。
  3. 根据在三级缓存池中的半成品类A,成功完成类B的创建。然后从三级缓存池放入二级缓存池earlySingletonObjects再放入一级缓存池。
  4. 类A从一级缓存池singletonObjects成功获取类B,完成对象的创建。成功的解决了循环依赖的问题。

image-20210327180207741

4. spring 源码看循环依赖解决
  1. 创建类A后开始填充其属性类B

    image-20210327172107127

  2. 半成品类A对象放入三级缓存中

    image-20210327171847756

  3. 类B根据三级缓存池中的半成品类A对象完成创建放入二级缓存当中

    image-20210327172921280

  4. 把二级缓存池中的完成的对象类B放入一级缓存池

    image-20210327173210673

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值