Spring三级缓存
P42
1.单例池 singletonObjects
2.第二级缓存 earlySingletonObjects
3.第三季缓存 singletonFactories
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<String, Object>(16);
填充service属性对应步骤在DefaultSingletonBeanRegistry.java的getSingleton方法
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//先去一级缓存单例池中找
Object singletonObject = this.singletonObjects.get(beanName);
//如果以及缓存单例池没找到,并且需要的bean正在创建中(即循环依赖)并且二级缓存单例池没找到,并且允许循环引用,进入if
if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName) && (singletonObject = this.earlySingletonObjects.get(beanName)) == null && allowEarlyReference) {
Map<String, Object> map = this.singletonObjects;
//双重锁检测并保证下面的put和remove操作的原子性
synchronized (map) {
ObjectFactory<?> singletonFactory;
singletonObject = this.singletonObjects.get(beanName);
//第一级缓存空并且第二级缓存空并且第三季缓存不为空
if (singletonObject == null && (singletonObject = this.earlySingletonObjects.get(beanName)) == null && (singletonFactory = this.singletonFactories.get(beanName)) != null) {
singletonObject = singletonFactory.getObject();
//把对象放入二级缓存并且清除三级缓存内的lambbda表达式
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
return singletonObject;
}
第二步或者第五步什么时候执行aop关键看earlyProxyReferences 这个map是否有值
AbstractAutoProxyCreator.java
private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<Object, Object>(16);
//对应第五步aop
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
Object cacheKey;
if (bean != null && this.earlyProxyReferences.remove(cacheKey = this.getCacheKey(bean.getClass(), beanName)) != bean) {
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
return bean;
}
//对应第二步aop
public Object getEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return this.wrapIfNecessary(bean, beanName, cacheKey);
}