Spring循环依赖问题的产生与解决方式

1,什么是循环依赖

循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对象,最终形成闭环。比如A依赖于B,B依赖于A

2,怎么解决循环依赖问题

需要设置属性值,构造器无法解决循环依赖,只有set方法可以解决——(提前暴露对象)
在这里插入图片描述
对象在创建的过程中,是把实例化和初始化分开的,那么意味着中间可能存在一种状态,完成实例化但未完成初始化的状态。因为spring默认是单例的,把上述状态的对象拿出来放到某个空间,或者放到集合中(Map)(提前暴露对象)。后面可以通过当前集合对象的引用设置具体的属性值
在这里插入图片描述
结论:对象创建过程中,实例化和初始化是分开进行的,互不干扰。

DefaultSingletonBeanRegistry.java
/** Cache of singleton objects: bean name to bean instance. 一级缓存 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** Cache of singleton factories: bean name to ObjectFactory. 三级缓存 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** Cache of early singleton objects: bean name to bean instance. 二级缓存*/
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
3,三个缓存中存放的对象有什么区别
  • 一级缓存中放的是完整对象
  • 二级缓存中放的是半成品对象(完成了实例化但是未完成初始化)
  • 三级缓存中放的是lambda表达式对象
4,缓存中的对象是如何移动的

A : 三级缓存 ——> 二级缓存 ——> 一级缓存
B:三级缓存 ——> 一级缓存

5,能否直接使用一级缓存来解决循环依赖问题

一级缓存和二级缓存存放的是不同类型的对象,如果只有一级缓存,那么成品和半成品都会放到一起,在调用过程中,可能会获取到半成品对象

6,二级缓存能否解决循环依赖问题

此时,看起来是可以解决的。如果在循环依赖的过程中,不包含aop动态代理的话, 那么直接使用二级缓存足以解决问题,但当出现了aop动态代理之后,必须要使用三级缓存

7,为什么使用三级缓存

如果一个对象需要对代理,那么会通过反射的方式生成普通对象吗?通过反射的方式创建的普通对象一定会创建,只不过当需要动态代理的时候,会完成当前对象的替换工作, 在整个容器中,可能存在普通对象和代理对象,但是暴露给别人使用的一定是最终版本的对象(要么是普通对象,要么是代理对象)。

8,为什么使用lambda表达式就可以解决这个问题?

回调机制,当需要给外部暴露对象的时候,使用lambda表达式的回调方式能够最终返回出一个唯一的最终版本的对象,而我们在使用过程中,是无法判断或者设置什么时候被调用的,所以当第一次被调用的时候直接通过lambda表达式生成即可。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子非我鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值