一天,侄子和我哥聊天,我坐在旁边听着
侄子:爸爸,你爱我妈妈吗?
哥:这话说的,不爱能有你吗?
侄子:确定有我不是因为荷尔蒙吗?
哥:因为什么荷尔蒙,因为爱情!
侄子:那我妈花点钱,你咋老说呢?
哥:这你就不懂了,挣钱本不易,花钱要仔细
侄子:快得了吧,挣钱这么少,我妈都没跑,给你照顾家,钱还不让花
哥:我发现你这孩子怎么不知道好赖呢,我攒钱不是为了给你去媳妇啊
侄子:那你赶紧给我妈花吧,我妈要是跑了,你还得花钱娶一个,到最后,钱我捞不着,亲妈还混没了
我:通透!!!
写在前面Spring 中常见的循环依赖有 3 种:单例 setter 循环依赖、单例构造方法循环依赖、原型循环依赖
关于单例 setter 循环依赖,Spring 是如何甄别和处理的,可查看:Spring 的循环依赖,源码详细分析 → 真的非要三级缓存吗
单例构造方法循环依赖何谓单例构造方法循环依赖了,我们看具体代码就明白了
两个要素:① scope 是默认值,也就是 singleton;② 多个实例之间通过构造方法形成了循环依赖
这种情况下,Spring 是怎么处理的了,我们先来看看执行结果
Spring 启动过程中报错了: Error creating bean with name 'cat': Requested bean is currently in creation: Is there an unresolvable circular reference?
问题就来了:Spring 是如何甄别单例情况下的构造方法循环依赖的,然后进行报错的
大家先把这个问题暂留在心里,我们再来看看什么是原型循环依赖
原型循环依赖同样,我们直接看代码就明白何谓原型循环依赖了
同样是 2 个要素:① scope 不是默认值,而是 prototype,也就是原型,每次获取该实例的时候都会新建;② setter 循环依赖
这种情况下 Spring 又会有什么样的执行结果了
Spring 启动正常,但从 Spring 容器获取 loop 实例的时候,报了同样的错误
问题来了:① Spring 是如何甄别原型循环依赖的,然后进行报错提示的
② 为什么两种情况的报错时机会不一致,一个在 Spring 启动过程中,一个却在使用 Spring 的过程中
示例代码地址:spring-circle-dependence-type
上面的 3 个问题,概括下就是
1、Spring 是如何甄别单例情况下的构造方法循环依赖的
2、Spring 是如何甄别原型循环依赖的
3、为什么单例构造方法循环依赖和原型循环依赖的报错时机不一致
我们慢慢往下看,跟源码的过程可能比较快,大家看仔细了
还是那句话
看完之后仍有疑问,可以评论区留言,也可以自行去查阅相关资料进行解疑
源码起点Spring 读取和解析 xml 的过程,我们就不去跟了,我们重点跟一下我们关注的内容
我们从 DefaultListableBeanFactory 类的 preInstantiateSingletons 方法作为起点
按如下顺序可以快速的找到起点,后面两种情况都从此处开始进行源码跟踪
构造方法循环依赖的甄别闲话少说,我们直接开始跟源码
获取 cat 实例