Spring——Spring中的三级缓存到底咋回事

循环依赖是什么

有一个类A,一个类B。在A类中有个B类的属性值b,在B类中有个A类的属性值a。那么由于在Spring中,对象bean默认都是单例的,那就意味着整个容器中只有一个该类的实例对象。
那么在Spring容器中创建A类对象的时候,要给B类的b属性赋值的时候,就会跑去创建B类对象,然后在创建B类对象的时候,又发现要用到A类的属性a,又回去继续创建A类对象,反复如此造成了一个闭环无解的局面,就是循环依赖。
在这里插入图片描述

通过缓存解决循环依赖(一级缓存)

对象的创建通常包括实例化和初始化,实例化就是在堆中开辟一块空间,初始化才是进行对象的赋值等等操作。那么我们就能将上诉的闭环过程分析的再详细一点。
在这里插入图片描述
这时候再来看这个闭环,就能比较清楚的发现,这个闭环造成的根本原因是在实例化之后的初始化填充属性的时候。
这里既然对象已经实例化了,那么其实也就是说我们完全可以先拿来用实例化好的半成品对象,后面再给他填充属性,那么这个闭环不就解开了。所以这里就有了一级缓存,用来存放半成品对象。
那么这样,无论是从蓝色的创建A对象开始,还是从橙色的创建B对象开始,最终都会到紫色的一级缓存中去拿另一个对象的半成品来填充自己的的属性,以此初步解开闭环。
在这里插入图片描述

二级缓存

仅有一个一级缓存肯定不够的。如果仅通过一级缓存来处理,由于放的都是半成品,所以这个时候对于A和B两个对象来说他们是成品了,但是他们里面各自的属性b和a由于是从一级缓存中拿出来的,所以任然是半成品。
在这里插入图片描述
那么这个时候,就需要二级缓存了。二级缓存就是用来放A和B的成品的。并最终让他们赋值到各自所需要的属性中,让他们的属性也变成成品。
在这里插入图片描述

为什么一定要三级缓存

我们先要明白一件事情,如果一个对象需要被代理,生成代理对象,那么这个对象需要被预先生成非代理对象。
那么如果你不用aop,二级缓存就足够解决问题,但如果你需要用到aop,并且你的循环依赖中的对象需要被aop代理的情况下,二级缓存就不够用了,所以在Spring中的三级缓存中存放的就是代理对象。

结论

  • 一二三级缓存分别干了什么的?
    • 上述一二三级缓存存放的内容,只是为了方便说清楚循环依赖。在Spring源码中,一级缓存放成品对象,二级缓存放成品半成品对象,三级缓存放的式一个函数时接口
  • 如果只使用一级缓存行不行?
    • 不行,最少需要二级缓存,如果强行把一二级缓存都放在一起,只用一级缓存,由于缓存都是map结构,key为bean的名字,所以在进行对象获取的时候无法保证获取到的是成品对象还是半成品对象。
  • 二级缓存行不行?
    • 如果没有aop的话,二级缓存足够解决循环依赖问题。
  • 三级缓存到底做了什么事?
    • 三级缓存中存放的是一个lambda表达式。由于在容器中,对象默认都是单例的,意味着根据名称只能获取一个对象的值,此时同时存在两个对象的话,使用的时候无法判断和保证获取到哪一个对象,所以为了保证任何时候都只有一个对象供外部调用,所以在三级缓存中,完成了一件把非代理对象替换为代理对象的工作,确定返回的是唯一对象
  • 为什么不把三级缓存中的lambda函数放到外部直接调用?
    • 因为我们无法确定什么时候需要用到这个三级缓存,无法确定在什么过程中需要生成代理对象,这些都是在程序运行过程中自动执行的,而非人为调用的。所以用三级缓存的map结构,key为对象名,value为该lambda函数,用来在执行过程中逻辑判断的时候,根据当前执行到的对象的对象名,自动的判断调用。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Java大魔王

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

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

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

打赏作者

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

抵扣说明:

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

余额充值