spring缓存
各级缓存
spring中有三级缓存:一级二级三级。三个都是存储bean相关的内容,但是具体存储的内容有所差异。
一级缓存 | 二级缓存 | 三级缓存 | |
---|---|---|---|
名称 | singletonObjects | earlySingletonObjects | singletonFactories |
类型 | ConcurrentHashMap | HashMap | HashMap |
定义 | 定义是在DefaultSingletonBeanRegistry类中 | 定义是在DefaultSingletonBeanRegistry类中 | 定义是在DefaultSingletonBeanRegistry类中 |
缓存内容 | 存放就绪状态的Bean | 早期曝光的Bean | 创建用于获取Bean的工厂类-ObjectFactory实例 |
一级缓存:就绪状态的bean,保存在该缓存中的Bean所实现Aware子接口的方法已经回调完毕,自定义初始化方法已经执行完毕,也经过BeanPostProcessor实现类的postProcessorBeforeInitialization、postProcessorAfterInitialization方法处理。
二级缓存:早期曝光的bean,一般只有处于循环引用状态的bean才会被保存在该缓存中,所实现的Aware子接口方法还未回调,自定义初始化方法还未执行。
三级缓存:存放获取bean的工厂类-ObjectFactory实例,在IoC容器中,所有刚被创建出来的bean,默认都会保存到该缓存中。
解决循环依赖问题
什么是循环依赖:
1 |
|
在 A 和 B 循环依赖的场景中:
B populatedBean
查找依赖项 A 的时候,从一级缓存中虽然未获取到 A,但是发现 A 在创建中。
此时,从三级缓存中获取 A 的 singletonFactory
调用工厂方法,创建 getEarlyBeanReference
A 的早期引用并返回。
B 引用到 A ,B 就可以初始化完毕,然后 A 同样也可以初始化完毕了。
AOP代理
说是二级缓存其实已经能解决循环依赖的问题,但是为什么需要三级缓存呢。说是解决AOP代理的问题。
如果只有二级缓存,虽然能解决循环依赖,但是在查询二级缓存中返回的实例,而不是我们需要的代理对象,所以添加了三级缓存,在三级对象中获取实例的时候,会经过判断,如果是代理对象则返回代理对象,如果是实例就返回实例。
其实具体的我说的也不是很清楚,可以参考连接:https://zhuanlan.zhihu.com/p/377878056