spring缓存

各级缓存

spring中有三级缓存:一级二级三级。三个都是存储bean相关的内容,但是具体存储的内容有所差异。

一级缓存 二级缓存 三级缓存
名称 singletonObjects earlySingletonObjects singletonFactories
类型 ConcurrentHashMap HashMap HashMap
定义 定义是在DefaultSingletonBeanRegistry类中 定义是在DefaultSingletonBeanRegistry类中 定义是在DefaultSingletonBeanRegistry类中
缓存内容 存放就绪状态的Bean 早期曝光的Bean 创建用于获取Bean的工厂类-ObjectFactory实例

image-20240427123420433

一级缓存:就绪状态的bean,保存在该缓存中的Bean所实现Aware子接口的方法已经回调完毕,自定义初始化方法已经执行完毕,也经过BeanPostProcessor实现类的postProcessorBeforeInitialization、postProcessorAfterInitialization方法处理。

二级缓存:早期曝光的bean,一般只有处于循环引用状态的bean才会被保存在该缓存中,所实现的Aware子接口方法还未回调,自定义初始化方法还未执行。

三级缓存:存放获取bean的工厂类-ObjectFactory实例,在IoC容器中,所有刚被创建出来的bean,默认都会保存到该缓存中。

解决循环依赖问题

什么是循环依赖:

1
2
3
4
5
6
7
8
9
10
11
@Service
public class CircularServiceA {
@Autowired
private CircularServiceB circularServiceB;

}
@Service
public class CircularServiceB {
@Autowired
private CircularServiceA circularServiceA;
}

在 A 和 B 循环依赖的场景中:

B populatedBean 查找依赖项 A 的时候,从一级缓存中虽然未获取到 A,但是发现 A 在创建中。

此时,从三级缓存中获取 A 的 singletonFactory 调用工厂方法,创建 getEarlyBeanReference A 的早期引用并返回。

B 引用到 A ,B 就可以初始化完毕,然后 A 同样也可以初始化完毕了。

image-20240427154008953

AOP代理

说是二级缓存其实已经能解决循环依赖的问题,但是为什么需要三级缓存呢。说是解决AOP代理的问题。

如果只有二级缓存,虽然能解决循环依赖,但是在查询二级缓存中返回的实例,而不是我们需要的代理对象,所以添加了三级缓存,在三级对象中获取实例的时候,会经过判断,如果是代理对象则返回代理对象,如果是实例就返回实例。

其实具体的我说的也不是很清楚,可以参考连接:https://zhuanlan.zhihu.com/p/377878056