博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring的一、二、三级缓存
阅读量:4170 次
发布时间:2019-05-26

本文共 1578 字,大约阅读时间需要 5 分钟。

属性暂时没有值的对象称之为不完整的Bean对象。

第一级缓存:单例池

singletonObjects ConcurrentHasnMsp<beanName,bean对象>
作用:保证一个beanName对应唯一的Bean完整对象

第二级缓存

earlySingletonObjects HashMap<beanName,bean对象>
作用:保证一个beanName对应唯一的Bean不完整对象

第三级缓存

singletonFactory HashMap<beanName,ObjectFactory(lambda表达式)>
作用:做一些预备工作。创建bean的时候先存到三级缓存,并不知道后面逻辑会不会用,会不会出现循环依赖等,防止出现循环依赖且AOP等场景

@Component("aService")public class AService(){
@Autowired private BService bService; public void xxx(){
}}
@Component("bService")public class BService(){
@Autowired private AService aService; public void xxx(){
}}

加了三级缓存之后,生命周期如下:

0. creatingSet

  1. 实例化…AService不完整对象(new AService())即原始对象—>第三级缓存<‘aSerivce’,lambda(AService原始对象,beanName,Beanefinition)>

  2. 填充bService属性—>从单例池中找bService—>找不到—>创建bService

    bService的生命周期

    2.1 实例化…BService对象(new BService())
    2.2 填充aService属性—>从单例池中找aService—>找不到—>aService正在创建中—>aService出现了循环依赖—>第二级缓存—>第三级缓存—>执行lambda—>提前AOP—>得到代理对象—>放入第二级缓存<‘aSerivce’,AService代理对象>
    2.3 填充他属性
    2.4 做其他事情
    2.5 放入单例池

  3. 填充他属性

  4. 做其他事情

  5. 从二级缓存中取出AService对象

  6. 放入单例池

  7. creatingSet.remove(“aService”)

部分源码解释

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

从上述定义,可看出:一级缓存(单例池)使用的是ConcurrentHashMap,二级缓存和三级缓存都是用的HashMap

为什么二级缓存和三级缓存用HashMap而不是使用ConcurrentHashMap呢?难道就不考虑线程安全的问题吗?

由于三级缓存中存的是lambda表达式且是一次性的,只要执行过一次就会被移除。二级缓存中存的是三级缓存lambda执行的结果。
也就是说同一个bean的名字,在三级缓存中如果存在一个lambda表达式,那么就表示在二级缓存中beanName对应的就没有值。同样的,反过来,在二级缓存里面beanName有值,那么在三级缓存中就没有对应的表达式。相当于是原子性的。
从第二段代码中可以看出,在往二级缓存push的时候,会把三级缓存的数据清除掉,那么就必须保证操作的原子性。很显然,二级缓存和三级缓存定义为ConcurrentHashMap并不能保证操作的原子性。只能添加synchronize加锁控制。
结合第二三段代码,可以看到,两个map的操作总是在一起的,添加到一个里面就从另一个中移除,同时加锁控制,已经保证了并发的操作安全,所以就没有必要设置为ConcurrentHashMap,在这种前提下,考虑性能,选择了HashMap

转载地址:http://oayai.baihongyu.com/

你可能感兴趣的文章
Ubuntulinux离线安装ClamTk杀毒软件步骤和使用方法
查看>>
摆脱贫穷2021V1
查看>>
Android.Could not find *.apk
查看>>
JNI
查看>>
Android基于TranslateAnimation的动画动态菜单
查看>>
android NDK中的GCC编译器
查看>>
Android NOtification 使用
查看>>
Android的SharedPreferences保存与删除数据简单实例
查看>>
android 如何从sqlite读取数据到spinner下拉中显示
查看>>
Android实现开机自动运行程序
查看>>
最近几天搭建MySql且连接问题总结
查看>>
搭建Tomcat
查看>>
在MyEclipse中运行tomcat出现Error initializing endpoint错误
查看>>
JSP文件中的上传功能(JSP中的相对路径)------JSP
查看>>
jsp中上传文件的源代码
查看>>
使用SQL语句查询表中重复记录并删除
查看>>
将xml中的数据导入到数据库
查看>>
Qt容器测试
查看>>
自定义插件
查看>>
编译数据库ODBC
查看>>