Spring 底层源码之解决循环依赖(五)

1. 产生的条件

在容器启动时,创建非懒加载的单例bean A,执行A的生命周期

  1. 实例化A
  2. 填充A的b属性-->查单例池-->没有则创建B,执行B的生命周期
    1. 实例化B
    2. 填充B的a属性-->查单例池-->没有则创建A... 此处产生循环依赖
  3. 初始化前,初始化,初始化后
  4. 放入单例池

2.打破循环依赖:引入二级缓存

  1. 实例化A--> 放入二级缓存
  2. 填充A的b属性
    1. 实例化B
    2. 填充B的a属性-->查单例池-->查二级缓存有,打破循环

虽然这里B对象填充的a属性暂时没有经过完整的生命周期,但是对象引用的是同一个地址,后续等到A对象处理完生命周期,B对象的a属性自然就是完整的bean,所以不是主要的问题

    3. 初始化前,初始化,初始化后

    4. 放入单例池

3.上述主要存在的问题:如果A创建的是AOP代理对象,那么创建B时属性注入的A属性应该也要是代理对象

如何解决:只有出现循环依赖,才让bean提前进行AOP得到代理对象。不能违反

  1. 标记A正在创建
  2. 实例化A
  3. 填充A的b属性
    1. 标记B正在创建
    2. 实例化B
    3. 填充B的a属性-->查单例池-->判断如果A正在创建-->查二级缓存-->判断A是否需要AOP?代理对象 : 原始对象 -->放入二级缓存

如果B对象注入属性c,创建对象C时也依赖了a属性,根据单例的设计原则,避免重复创建代理对象,所以要先查二级缓存

   4. 初始化前,初始化,初始化后

   5. A放入单例池

4.原始对象从哪里来?难道方法逐层传递?Spring采用函数接口编程

如何解决:只有出现循环依赖,才让bean提前进行AOP得到代理对象。不能违反

  1. 标记A正在创建
  2. 实例化A-->放入三级缓存
  3. 填充A的b属性
    1. 标记B正在创建
    2. 实例化B
    3. 填充B的a属性-->查单例池-->判断如果A正在创建-->查二级缓存-->三级缓存:执行lambda表达式创建代理对象或者返回原始对象-->放入二级缓存

1. 三级缓存:<beanname,lambda<A原始对象>>

2. 执行lamb表达式:调用后置处理器的回调方法,还会向earlyProxyReferences添加缓存标记。因为bean提前进行过AOP,后续执行初始化后的回调方法会用来判断,不需要再重复进行AOP

   4. 初始化前,初始化,初始化后

   5. A放入单例池

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值