spring是如何解决循环依赖

spring 的bean在创建bean的过程中会涉及到几个集合
1. singltonOjects:一级缓存(单例池)
2. earlySingltonObjects:二级缓存
3. singltonFactories:三级缓存
4. singletonsCurrentlyInCreation:存放正在创建bean的set集合,存放的是正在创建的bean的名字
** 一级缓存 ** :一级缓存就是我们常常说的spring的单例容器,spring依赖注入的bean都是从这个单例池中去获取的,创建后完整的bean也是存放在这个单例池中的,我们这里叫它为一级缓存;  
** 二级缓存 ** :二级缓存从名字上可以知道是叫做早期的单例对象,就是说它是存放的是早期的单例对象,可能是不完整的;  
** 三级缓存 ** :存放的是我们的实例化后的原始对象,就是存放一个刚刚被创建出来的原始对象。
首先我们的一个对象被创建出来过后会放入三级缓存中,移除二级缓存,三级缓存存放的是beanName对应的一个lambad表达式,这个表达式封装了刚刚实例化出来的对象、bean对应的BeanDefinition、beanName封装在一个ObjectFactory中,所以这个时候存放到三级缓存中的只是一个lambad表达式,当调用ObjectFactory的getObject的时候才会去执行lambad表达式,也就是方法的调用; 如果整个过程中没有出现循环依赖,那么永远不会使用到二级缓存,而且三级缓存也只是存放了实例化后封装的对象,也不会去使用;  
当出现了循环依赖的时候,那么这个时候就会启用二级和三级缓存,首先从三级缓存取出对象,然后执行getObject,将返回的对象(如果出现了循环依赖,而又开启了aop,返回的是一个代理对象)放入二级缓存,然后移除三级缓存;到这里可以得到一个知识点就是二级缓存和三级缓存是一对儿存在的,就是一个对象要么在二级缓存,要么在三级缓存,他们两个是成对出现的,存入二级缓存的时候,移除三级缓存,存入三级缓存的时候,移除二级缓存
  ```
@Component
public class AService {
   
   @Autowired
   private BService bS;
}
@Component
public class BService {

   @Autowired
   private AService aS;
}
```
上面这两个Bean是相互依赖的,也就是循环依赖的,加入spring首先扫描到是AService,那么AService的过程如下:  
**AService创建过程**:  
1. 实例化AService,得到AService的原始对象 aS,将实例化后的对象aS放入—>三级缓存
2. 填充aS中的bS->去容器找bS->找不到->进入创建BService的流程—>将返回的bS对象复制给AService中的bS;
3. 填充其他属性;
4. 初始化bean;
5. 放入一级缓存单例池。
6. 移除bS在二级、三级缓存中的对象
**BService创建过程**:  
1. 实例化BService,得到BService的原始对象 bS,将实例化后的对象bS放入—>三级缓存;
2. 填充bS中的aS->去容器找aS->判断as是否正在被创建—>从三级缓存获取aS—>调用三级缓存获取的lambad表达式(当出现了循环依赖,如果bean启用了循环依赖,** 这里调用lambad会执行aop **,返回一个代理对象)—>将得到的对象放入二级缓存—>移除三级缓存–>返回A的实例对象–>赋值给BService 中的aS;
3. 填充其他属性;
4. 初始化bean;
5. 放入一级缓存单例池(返回bS给Aservice的第二步)。
6. 移除bS在二级、三级缓存中的对象。
**当AService创建完成过后,然后去创建BService,发现BService已经被创建了,因为创建Aservice的时候出现了循环依赖,就已经去创建了BService,所以这样就处理完成了。**

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值