spring中的三级缓存
- 一级缓存:singletonObject 存放已经经历了完整周期的Bean对象
- 二级缓存:earlySingletonObjects 存放早期暴露出来的Bean对象,Bean的生命周期未结束
- 三级缓存:singletonFactories 存放可以生成Bean的工厂
三个Map有什么异同
缓存其实就是三个Map
- 一级缓存:它是spring容器,存放完整的Bean实例,已经实例化和初始化好的实例
- 二级缓存:bean不管是否被AOP切面代理,“否”代表保存半成品的Bean实例,属性未填充,“是”代表,保存代理的实例BeanProxy,Bean还是半成品
- 三级缓存:存放的是ObjectFactory,传入的是一个匿名内部类,ObjectFactory.getObject()最终调用的是getEarlyBeanReference方法
什么是循环依赖
循环依赖:就是 N 个类循环(嵌套)使用。就是多个 Bean 之间互相依赖或引用到对方,最终形成了 闭环。
spring的三级缓存就
是为了解决对象间的循环依赖问题。
A依赖B,B依赖A,这就是一个简单的循环依赖。
查看spring三级缓存的源码
查看路径
package org.springframework.beans.factory.support;
四个关键的方法
getSingleton(),doCreatBean(),populateBean(),addSingleton()
1.获取Bean的源码
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
//一级缓存
private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
//二级缓存
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap(16);
//三级缓存
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
//已经注册的单例池里的beanName
private final Set<String> registeredSingletons = new LinkedHashSet(256);
//正在创建中的beanName集合
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap(16));
@Nullable //缓存查找bean 如果第1级缓存没有,那么从第2级缓存获取。如果第2级缓存也没有,那么从第3级缓存创建,并放入第2级缓存
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized(this.singletonObjects) {
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
//第3级缓存 在doCreateBean中创建了bean的实例后,封装ObjectFactory放入缓存的bean实例
ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//创建未赋值的Bean
singletonObject = singletonFactory.getObject();
//存放到二级缓存中
this.earlySingletonObjects.put(beanName, singletonObject); //从三级缓存中删除
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}
}
2.“添加到第1级缓存”的源码:
protected void addSingleton(String beanName, Object singletonObject) {
synchronized(this.singletonObjects) {
//放入一级缓存中
this.singletonObjects.put(beanName, singletonObject);
//从第三级缓存中删除
this.singletonFactories.remove(beanName);
//从第二级缓存中删除
this.earlySingletonObjects.remove(beanName);
//放入已注册的单例池里
this.registeredSingletons.add(beanName);
}
}
3.“添加到第3级缓存”的源码:
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized(this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
4.创建Bean的源码:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// 1. 从factoryBeanInstanceCache缓存中尝试获取
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 2. 如果缓存中不存在,则根据bean对应的策略创建新的实例,如:工厂方法、构造器自动注入、简单初始化
if (instanceWrapper == null) {
// Bean对象实例化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch ...
mbd.postProcessed = true;
}
}
// 3.是否需要提前曝光 = 单例&允许循环依赖&bean正在创建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//添加到第三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// 4. 对bean属性进行填充,注入bean中的属性
Object exposedObject = bean;
try {
//填充属性
populateBean(beanName, mbd, instanceWrapper);
//bean对象初始化
//调用初始化方法,比如init-method、注入Aware对象、应用后处理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch····
return exposedObject;
}
对于三级缓存解决循环依赖的问题
我们只能使用field 属性注入(setter方法注入)循环依赖
为什么不能使用 构造器注入循环依赖来解决
Spring 解决循环依赖依靠的是
Bean
的
"
中间态
"
这个概念,而这个中间态指的是已经实例化但还没初始化的状态
—>半成品。实例化的过程又是通过构造器创建的,如果 A 还没创建好出来怎么可能提前曝光,所以构造器的循环依赖无法解决
由于 spring
中的
bean
的创建过程为先实例化 再初始化
(
在进行对象实例化的过程中不必赋值
)
将实例化好的对象暴露出去,
供其他对象调用
,
然而使用构造器注入
,
必须要使用构造器完成对象的初始化的操作
,就会陷入死循环的状态
一级缓存能不能解决循环依赖问题?
不能,因为在三个级别的缓存中存储的对象是有区别的 一级缓存为完全实例化且初始化的对象 二级缓存实例化但未初始化对象,Bean对象还是一个半成品 如果只有一级缓存,如果是并发操作下,就有可能取到实例化但未初始化的对象,就会出现问题
二级缓存能不能解决循环依赖问题?
理论上二级缓存可以解决循环依赖问题
,
但是需要注意——>
为什么需要在三级缓存中存储匿名内部类 (ObjectFactory)
原因在于"需要创建代理对象 eg:现有A类,需要生成代理对象 A ,需要进行实例化"
在三级缓存中:存放的是ObjectFactory,传入的是一个匿名内部类,ObjectFactory.getObject()最终调用的是getEarlyBeanReference方法,该类可能是代理类也可能是普通的对象,而使用三级缓存可以保证 无论是否需要是代理对象,都可以保证使用的是同一个对象,而不会出现,一会儿使用普通 bean 一会儿使用代理类