Spring 循环依赖问题

Spring 循环依赖问题

解决循环依赖的前置条件

  • 出现循环依赖的 Bean 必须是单例的
  • 依赖注入的方式不能都是构造注入的方式

整体过程

Spring 通过三级缓存解决了循环依赖问题, 一级缓存为单例池, 二级缓存为早期暴光对象, 也就是还没有属性注入及初始化的对象, 三级缓存为早期暴露的单例工厂, 二级缓存中存储的就是从这个工厂获取的对象

  1. 调用 doGetBean() 方法, 想要获取 beanA, 于是调用 getSingleton() 方法从缓存中查找 beanA
  2. getSingleton() 方法中, 从一级缓存中查找, 没有并返回null
  3. doGetBean() 方法中获取的 beanA 为 null, 于是走到对应的处理逻辑, 调用 getSingleton() 参数为 ObjectFactory 的重载方法
  4. getSingleton() 方法中, 先将 beanA_name 添加到一个集合中, 用于标记该 bean 正在创建, 然后回调匿名内部类的 createBean() 方法
  5. 进入 doCreateBean() 方法, 先反射调用构造器创建出 beanA 的实例, 然后判断是否为单例, 是否允许提前暴露引用, 单例一般为 true, 是否正在创建中, 判断为 true 则将 beanA 添加到三级缓存中
  6. 对 beanA 进行属性填充, 此时检测到 beanA 依赖于 beanB, 于是开始查找 beanB
  7. 调用 doGetBean() 方法, 与上面的 beanA 过程一样, 到缓存中查找 beanB, 没有则创建, 然后进行属性填充
  8. 此时 beanB 依赖于 beanA, 调用 getSingleton() 获取到 beanA, 依次从一级, 二级, 三级缓存中查找, 此时从三级缓存中获取到 beanA 的创建工厂, 通过创建工厂获取到 singletonObject 指向的就是 doCreateBean() 方法中实例化的 beanA
  9. 这样 beanB 就获取到 beanA 的依赖, 于是beanB 顺利的完成实例化, 并将 beanA 从三级缓存中移动到二级缓存中
  10. 随后 beanA 继续他的属性填充工作, 也能获取到 beanB, 此时可以完成创建, 回到 getSingleton() 方法中继续向下执行, 将 beanA 从二级缓存移动到一级缓存中

整体过程图示

在这里插入图片描述

没有 AOP

在这里插入图片描述

有 AOP

在这里插入图片描述

二级缓存能解决循环依赖问题吗

使用二级缓存解决循环依赖, 意味着所有的 Bean 在实例化后就要完成 AOP 代理, 违背了 Spring 的设计原则, 设计之初就是通过后置处理器来在 bean 的生命周期的最后一步来完成 AOP 代理, 而不是在实例化后就进行 AOP 代理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值