Spring循环依赖和三级缓存


发表于 修改于 后端知识整理 689 字 4 分钟

Spring加载流程&Bean的生命周期

推荐篇博文 Spring中bean的生命周期(最详细)

循环依赖

解决循环依赖的关键是将【实例化】与【初始化】两个过程分开。

二级缓存

假设只使用二级缓存,能否解决循环依赖问题?答案是可以。 但是这仅限于在未使用AOP生成代理对象的情况下

代理对象实例化的时候,实例化对象是原始对象 若没有三级缓存,此时若根据类名直接获取对象的话,获取的是原始对象 而我们想要的肯定是通过类名直接获取代理对象 所以Spring在类加载过程中,直接将实例化的对象放入三级缓存中 从三级缓存中获取类对象的时候,判断类是否被代理,若被代理则返回代理对象

三级缓存

Spring在启动过程中,使用到了三个map,称为三级缓存。

引用自https://blog.csdn.net/wuwu12dfda/article/details/105155065

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
/**
* Cache of singleton objects: bean name to bean instance.
* 【一级缓存】用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用。
*/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/**
* Cache of singleton factories: bean name to ObjectFactory.
* 【三级缓存】用于存放 bean 工厂对象ObjectFactory(三级缓存中Bean的代理对象)
* ObjectFactory.getObject()方法描述了如何获取这个三级缓存的对象。
*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/**
* Cache of early singleton objects: bean name to bean instance.
* 【二级缓存】用于存放提前暴露的单例对象的cache,原始的 bean 对象(尚未填充属性,半成品bean)。
*/
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
/**
* Names of beans that are currently in creation.
* 正在创建中的beanName
*/
private final Set<String> singletonsCurrentlyInCreation =
Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//缓存查找bean,双重检查提高并发效率
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//从一级缓存获取bean
Object singletonObject = this.singletonObjects.get(beanName);
//一级缓存中不存在,而且是在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//从二级缓存中获取bean
singletonObject = this.earlySingletonObjects.get(beanName);
//二级缓存中不存在,而且允许循环依赖
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
//从一级缓存获取bean
singletonObject = this.singletonObjects.get(beanName);
//一级缓存中不存在
if (singletonObject == null) {
//从二级缓存中获取bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//从三级缓存中获取返回扩展对象的工厂方法
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//获取扩展对象
singletonObject = singletonFactory.getObject();
//放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
//从三级缓存中移除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}

评论