首先,三级缓存是Spring用于处理单例Bean的创建和解决循环依赖问题的机制。在Spring中,单例Bean是指在整个应用程序上下文中只存在一个实例的Bean。
- 一级缓存:一级缓存是一个ConcurrentHashMap,用于存储完全初始化的单例Bean实例。当你通过Spring容器获取一个Bean时,首先会查找一级缓存,如果找到了完全初始化的Bean实例,直接返回。
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
- 二级缓存:二级缓存也是一个Map,用于存储早期(不完全初始化)的Bean实例。当Bean正在创建但尚未完全初始化时,它会被放入二级缓存,以便在解决循环依赖问题时能够提供一个引用。同时,二级缓存中的Bean实例通常会是代理对象。
private final Map<String, Object> earlySingletonObjects = new HashMap<>();
- 三级缓存:三级缓存是一个Map,用于存储Bean的工厂对象(
ObjectFactory
)。这些工厂对象负责创建Bean的实例。当解决循环依赖时,如果一个Bean A依赖于另一个Bean B,Bean B的工厂对象会被放入三级缓存中。这是为了确保在创建Bean A时,可以从三级缓存中获取Bean B的工厂对象,以便创建中的Bean A能够引用Bean B。
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
- Bean的创建和获取过程:当你通过Spring容器获取一个Bean时,容器会先检查一级缓存,如果找到完全初始化的Bean实例,直接返回。如果一级缓存中没有,容器会继续检查二级缓存,如果找到早期Bean实例,将其返回。同时,如果Bean A依赖于Bean B,Bean B的工厂对象会被放入三级缓存。容器会使用Bean B的工厂对象来创建中的Bean A,并将Bean A的早期实例放入二级缓存中。最后,当Bean A创建完成后,它会被移动到一级缓存中,三级缓存中的Bean B的工厂对象也会被移除。
这个三级缓存机制在Spring容器中非常重要,因为它解决了循环依赖问题,确保Bean的唯一性和正确初始化。
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {
// 一级缓存,用于存储完全初始化的Bean
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存,用于存储早期(不完全初始化)的Bean
private final Map<String, Object> earlySingletonObjects = new HashMap<>();
// 三级缓存,用于存储创建中的Bean工厂对象
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();
// 通过Bean名称获取Bean的方法
public Object getSingleton(String beanName) {
// 首先从一级缓存尝试获取完全初始化的Bean
Object singletonObject = singletonObjects.get(beanName);
if (singletonObject != null) {
return singletonObject;
}
// 如果一级缓存中没有,尝试从二级缓存获取早期Bean
singletonObject = earlySingletonObjects.get(beanName);
if (singletonObject != null) {
// 如果早期Bean存在,需要处理循环依赖
// 这时我们可以使用三级缓存的Bean工厂对象
// 在后续创建过程中,会将创建中的Bean工厂对象放入三级缓存
ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 将早期Bean转移到一级缓存中
singletonObjects.put(beanName, singletonObject);
// 移除三级缓存中的Bean工厂对象
singletonFactories.remove(beanName);
}
}
return singletonObject;
}
// 注册Bean工厂到三级缓存的方法
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
}
}
}
// ...
}