Spring中Bean的循环依赖与解决办法

发布于:2023-01-22 ⋅ 阅读:(6) ⋅ 点赞:(0) ⋅ 评论:(0)

一、Bean的循环依赖

1.1 自我依赖 A依赖A

在这里插入图片描述

1.2 A、B互相依赖

在这里插入图片描述

1.3 三者或多者依赖

在这里插入图片描述

二、三级缓存解决

在这里插入图片描述

2.1 只有一级缓存不能解决

分析一级缓存这样存放成品 Bean 的流程中,是不能解决循环依赖的问题的。

因为 A 的成品创建依赖于 B,B的成品创建又依赖于 A,当需要补全B的属性时 A 还是没有创建完,所以会出现死循环。

2.2 二级缓存能解决吗?

  • 有了二级缓存其实这个事处理起来就容易了,一个缓存用于存放成品对象另外一个缓存用于存放半成品对象
  • A 在创建半成品对象后存放到缓存中,接下来补充 A 对象中依赖 B 的属性。
  • B 继续创建,创建的半成品同样放到缓存中,在补充对象的 A 属性时,可以从半成品缓存中获取,现在 B 就是一个完整对象了,而接下来像是递归操作一样 A 也是一个完整对象了。

2.3 三级缓存解决什么?

  • 有了二级缓存都能解决 Spring 依赖了,怎么要有三级缓存呢。其实我们在前面分析源码时也提到过,三级缓存主要是解决 Spring AOP 的特性。
  • AOP 本身就是对方法的增强,是 ObjectFactory<?> 类型的 lambda 表达式,而 Spring 的原则又不希望将此类类型的 Bean 前置创建,所以要存放到三级缓存中处理。
  • 其实整体处理过程类似,唯独是 B 在填充属性 A 时,先查询成品缓存、再查半成品缓存,最后在看看有没有单例工程类在三级缓存中。最终获取到以后调用 getObject 方法返回代理引用或者原始引用。至此也就解决了 Spring AOP 所带来的三级缓存问题。本章节涉及到的 AOP 依赖有源码例子,可以进行调试

在这里插入图片描述

为什么非得要三级缓存(因为有的Bean对象是有AOP,需要代理的)

比如A对象是一个被AOP增量的对象,B依赖A时,得到的A肯定是代理对象;而三级缓存的Value是ObjectFactory,可以从里面拿到代理对象

在这里插入图片描述

参考:请问Spring是怎么解决Bean之间的循环依赖的?