|Spring循环依赖,我本来都不想写的,但网上好多错误观点( 三 )
- 实例化
- 属性注入
- 初始化
addSingletonFactory(beanName () -> getEarlyBeanReference(beanName mbd bean));
要注意 , 此时 Spring 是不知道会不会有循环依赖发生的 ,但是它不管, 反正往 singletonFactories 塞这个工厂 , 这里就是 提前暴露。
然后就开始执行属性注入 , 这个时候 A 发现需要注入 B , 所以去 getBean(B) , 此时又会走一遍上面描述的逻辑 , 到了 B 的属性注入这一步 。
此时 B 调用 getBean(A) , 这时候一级缓存里面找不到 , 但是发现 A 正在创建中的 , 于是去二级缓存找 , 发现没找到 , 于是去三级缓存找 , 然后找到了 。
并且通过上面提前在三级缓存里暴露的工厂得到 A , 然后将这个工厂从三级缓存里删除 , 并将 A 加入到二级缓存中 。
然后结果就是 B 属性注入成功 。
紧接着 B 调用 initializeBean 初始化 , 最终返回 , 此时 B 已经被加到了一级缓存里。
这时候就回到了 A 的属性注入 , 此时注入了 B , 接着执行初始化 , 最后 A 也会被加到一级缓存里 , 且从二级缓存中删除 A 。
Spring 解决依赖循环就是按照上面所述的逻辑来实现的 。
重点就是在对象实例化之后 , 都会在三级缓存里加入一个工厂 , 提前对外暴露还未完整的 Bean , 这样如果被循环依赖了 , 对方就可以利用这个工厂得到一个不完整的 Bean , 破坏了循环的条件 。
为什么循环依赖需要三级缓存 , 二级不够吗?上面都说了那么多了 , 那我们思考下 , 解决循环依赖需要三级缓存吗?
很明显 , 如果仅仅只是为了破解循环依赖 , 二级缓存够了 , 压根就不必要三级 。
你思考一下 , 在实例化 Bean A 之后 , 我在二级 map 里面塞入这个 A , 然后继续属性注入 。
发现 A 依赖 B 所以要创建 Bean B , 这时候 B 就能从二级 map 得到 A, 完成 B 的建立之后 ,A 自然而然能完成 。
所以 为什么要搞个三级缓存 , 且里面存的是创建 Bean 的工厂呢 ?
我们来看下调用工厂的 getObject 到底会做什么 , 实际会调用下面这个方法:
protected Object getEarlyBeanReference(String beanName RootBeanDefinition mbd Object bean) { Object exposedObject = bean; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) { exposedObject = bp.getEarlyBeanReference(exposedObject beanName);
return exposedObject;
重点就在中间的判断 , 如果 false , 返回就是参数传进来的 bean , 没任何变化 。
如果是 true 说明有
InstantiationAwareBeanPostProcessors。
且循环的是 smartInstantiationAware 类型 ,如有这个 BeanPostProcessor 说明 Bean 需要被 aop 代理。
我们都知道如果有代理的话 , 那么我们想要直接拿到的是代理对象 。
也就是说如果 A 需要被代理 , 那么 B 依赖的 A 是已经被代理的 A , 所以我们不能返回 A 给 B , 而是返回代理的 A 给 B 。
这个工厂的作用就是判断这个对象是否需要代理 , 如果否则直接返回 , 如果是则返回代理对象 。
看到这明白的小伙伴肯定会问 , 那跟三级缓存有什么关系 , 我可以在要放到二级缓存的时候判断这个 Bean 是否需要代理 , 如果要直接放代理的对象不就完事儿了 。
- 春天|今年春天又被《我和我的祖国》戳中了:这些脑内循环BGM你听过几首?
- 中企展开行动,降低“苹果依赖症”,央视的呼吁起效用了?
- 水循环|美媒报道:关于水的五个有趣事实
- 中企开始行动,央视呼吁降低“苹果依赖症”,有效果了?
- 京东科技与天奇股份达成深度合作 共建锂电池循环再利用平台
- 中企展开行动,降低“苹果依赖症”,央视的呼吁起效了?
- spring|苹果新款5G手机,为了赢取更大的市场,不惜拉起价格战
- spring|iPhoneX升级iOS15.4beta5:优化很棒!用着挺舒服,值得升级
- B站越来越像淘宝了,但营收依赖广告,前景够大吗?
- spring|OPPO Find X5竟然才3999元起?顿时感觉手里的三星S22不香了