再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

  一天,侄子和我哥聊天,我坐在旁边听着

  侄子:爸爸,你爱我妈妈吗?

  哥:这话说的,不爱能有你吗?

  侄子:确定有我不是因为荷尔蒙吗?

  哥:因为什么荷尔蒙,因为爱情!

  侄子:那我妈花点钱,你咋老说呢?

  哥:这你就不懂了,挣钱本不易,花钱要仔细

  侄子:快得了吧,挣钱这么少,我妈都没跑,给你照顾家,钱还不让花

  哥:我发现你这孩子怎么不知道好赖呢,我攒钱不是为了给你去媳妇啊

  侄子:那你赶紧给我妈花吧,我妈要是跑了,你还得花钱娶一个,到最后,钱我捞不着,亲妈还混没了

  我:通透!!!

再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

写在前面

  Spring 中常见的循环依赖有 3 种:单例 setter 循环依赖、单例构造方法循环依赖、原型循环依赖

  关于单例 setter 循环依赖,Spring 是如何甄别和处理的,可查看:Spring 的循环依赖,源码详细分析 → 真的非要三级缓存吗

  单例构造方法循环依赖

  何谓单例构造方法循环依赖了,我们看具体代码就明白了

再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

  两个要素:① scope 是默认值,也就是 singleton;② 多个实例之间通过构造方法形成了循环依赖

  这种情况下,Spring 是怎么处理的了,我们先来看看执行结果

再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

  Spring 启动过程中报错了: Error creating bean with name 'cat': Requested bean is currently in creation: Is there an unresolvable circular reference? 

  问题就来了:Spring 是如何甄别单例情况下的构造方法循环依赖的,然后进行报错的

  大家先把这个问题暂留在心里,我们再来看看什么是原型循环依赖

  原型循环依赖

  同样,我们直接看代码就明白何谓原型循环依赖了

再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

  同样是 2 个要素:① scope 不是默认值,而是 prototype,也就是原型,每次获取该实例的时候都会新建;② setter 循环依赖

  这种情况下 Spring 又会有什么样的执行结果了

再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

  Spring 启动正常,但从 Spring 容器获取 loop 实例的时候,报了同样的错误

  问题来了:① Spring 是如何甄别原型循环依赖的,然后进行报错提示的

       ② 为什么两种情况的报错时机会不一致,一个在 Spring 启动过程中,一个却在使用 Spring 的过程中

  示例代码地址:spring-circle-dependence-type

  上面的 3 个问题,概括下就是

    1、Spring 是如何甄别单例情况下的构造方法循环依赖的

    2、Spring 是如何甄别原型循环依赖的

    3、为什么单例构造方法循环依赖和原型循环依赖的报错时机不一致

  我们慢慢往下看,跟源码的过程可能比较快,大家看仔细了

  还是那句话

再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

  看完之后仍有疑问,可以评论区留言,也可以自行去查阅相关资料进行解疑

  源码起点

    Spring 读取和解析 xml 的过程,我们就不去跟了,我们重点跟一下我们关注的内容

    我们从 DefaultListableBeanFactory 类的 preInstantiateSingletons 方法作为起点

再探循环依赖 → Spring 是如何判定原型循环依赖和构造方法循环依赖的?

    按如下顺序可以快速的找到起点,后面两种情况都从此处开始进行源码跟踪

构造方法循环依赖的甄别

  闲话少说,我们直接开始跟源码

  获取 cat 实例

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzzgy.html