|Spring循环依赖,我本来都不想写的,但网上好多错误观点
文章图片
文章图片
文章图片
今天我们来盘 Spring 的经典面试题循环依赖 。
这的面试题很经典 , 网上相应的文章很多 , 但是我还是想写一下 , 因为有些文章的观点在我看来是错的 。
- 比如有构造器就无法解决循环依赖?
- 一定要三级缓存才能解决循环依赖?
- 到底为什么要三级缓存?
什么是循环依赖很简单 , 看下方的代码就知晓了
@Servicepublic class A { @Autowired
private B b;
@Servicepublic class B { @Autowired
private A a;
//或者自己依赖自己@Servicepublic class A { @Autowired
private A a;
上面这两种方式都是循环依赖 , 应该很好理解 , 当然也可以是三个 Bean 甚至更多的 Bean 相互依赖 , 原理都是一样的 , 今天我们主要分析两个 Bean 的依赖 。
这种循环依赖可能会产生问题 , 例如 A 要依赖 B , 发现 B 还没创建 。
于是开始创建 B, 创建的过程发现 B 要依赖 A ,而 A 还没创建好呀 , 因为它要等 B 创建好 。
就这样 它们俩就搁这卡 bug 了。
Spring 如何解决循环依赖上面这种循环依赖在实际场景中是会出现的 , 所以 Spring 需要解决这个问题 , 那如何解决呢?
关键就是 提前暴露未完全创建完毕的 Bean。
在 Spring 中 , 只有同时满足以下两点才能解决循环依赖的问题:
- 依赖的 Bean 必须都是单例
- 依赖注入的方式 , 必须 不全是 构造器注入 , 且 beanName 字母序在前的不能是构造器注入
所以 Spring 只支持单例的循环依赖 ,但是为什么呢 ?
按照理解 , 如果两个 Bean 都是原型模式的话 。
那么创建 A1 需要创建一个 B1 。
创建 B1 的时候要创建一个 A2 。
创建 A2 又要创建一个 B2 。
创建 B2 又要创建一个 A3 。
创建 A3 又要创建一个 B3.....
就又卡 BUG 了 , 是吧 , 因为原型模式都需要创建新的对象 , 不能跟用以前的对象 。
如果是单例的话 , 创建 A 需要创建 B , 而创建的 B 需要的是之前的个 A ,不然就不叫单例了 , 对吧?
也是基于这点 ,Spring 就能操作操作了 。
【|Spring循环依赖,我本来都不想写的,但网上好多错误观点】具体做法就是:先创建 A , 此时的 A 是不完整的(没有注入 B) , 用个 map 保存这个不完整的 A , 再创建 B, B 需要 A 。
所以从那个 map 得到“不完整”的 A , 此时的 B 就完整了 , 然后 A 就可以注入 B , 然后 A 就完整了 , B 也完整了 , 且它们是相互依赖的 。
读起来好像有点绕 , 但是逻辑其实很清晰 。
为什么不能全是构造器注入在 Spring 中创建 Bean 分三步:
- 实例化 , createBeanInstance , 就是 new 了个对象
- 属性注入 , populateBean ,就是 set 一些属性值
- 初始化 , initializeBean , 执行一些 aware 接口中的方法 , initMethod , AOP代理等
- 春天|今年春天又被《我和我的祖国》戳中了:这些脑内循环BGM你听过几首?
- 中企展开行动,降低“苹果依赖症”,央视的呼吁起效用了?
- 水循环|美媒报道:关于水的五个有趣事实
- 中企开始行动,央视呼吁降低“苹果依赖症”,有效果了?
- 京东科技与天奇股份达成深度合作 共建锂电池循环再利用平台
- 中企展开行动,降低“苹果依赖症”,央视的呼吁起效了?
- spring|苹果新款5G手机,为了赢取更大的市场,不惜拉起价格战
- spring|iPhoneX升级iOS15.4beta5:优化很棒!用着挺舒服,值得升级
- B站越来越像淘宝了,但营收依赖广告,前景够大吗?
- spring|OPPO Find X5竟然才3999元起?顿时感觉手里的三星S22不香了