Spring循环依赖为什么需要三级缓存?

if (earlySingletonExposure) {//默认为true
	if (logger.isTraceEnabled()) {
		logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
	}
    //把ObjectFactory存到三级缓存中,三级缓存中的Bean会被后置处理来增强:代理等
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 
}
.....
//给创建好的对象每个属性进行赋值,@Autowired发生在这里
populateBean(beanName, mbd, instanceWrapper); 
//初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
.....

说明:

  1. 上述代码是doCreateBean()里面的代码:首先默认将bean对应的ObjectFactory存入三级缓存中,然后属性赋值,初始化。
  2. 一级缓存存放成品bean的实例,二级缓存存放半成品bean,三级缓存存放ObjectFactory,可以在调用相应的方法时返回bean,其中二级缓存和三级缓存是专门来解决循环依赖的问题的。

原因:

  1. 解决循环依赖需要提前暴露半成品bean。
  2. 如果只有一级三级缓存,连半成品bean都没有,何从谈起解决循环依赖之说。
  3. 如果只有一级二级缓存,为了解决循环依赖,需要先将半成品bean存到二级缓存中暴露出来,但是又为了解决代理问题,暴露出来的bean还得是代理后的,所以需要此时(刚实例化bean后)就生成代理对象,否则:就会出现b中注入的a不是代理a的情况,但是spring设计之初是在bean初始化最后阶段代理,而不是在实例化后马上代理,所以加了三级缓存来延迟生成代理对象,这样只有在循环依赖这种情况下不得不用到bean的时候才生成代理bean并返回,没有循环依赖就不会生成代理bean,所以就保证了绝大多数情况还是会在初始化最后阶段生成代理对象。

总结:

其实笔者认为:spring用几级缓存无所谓,用几级都可以实现,只不过是spring做了一些取舍,最终用了三级,
如果把一二级缓存合成一个,#beanname表示成品bean,%beanname表示半成品bean,也是一样可以实现的,
只不过是丑陋、不太合理一点。

欢迎大家在评论区提出问题讨论,笔者看到会第一时间回复,如果觉得对你有帮助的话就点个赞吧。

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值