共计 3303 个字符,预计需要花费 9 分钟才能阅读完成。
一 spring 为什么要应用多级缓存
首先分明 spring 中 bean 的加载过程
1 解析须要 spring 治理的类为 beanDefinition
2 通过反射实例化对象
3 反射设置属性
4 初始化,调用 initMethod 等。(postConstruct 也是在这执行)
循环依赖的问题:a 依赖 b,b 依赖 a。
在 a 实例化之后会先将 a 放入到缓存中,而后给 a 设置属性,去缓存中查到 b。此时找不到就开始 b 的创立。b 实例化之后,放入到缓存中,须要给 a 设置属性,此时去缓存中查到 a 设置胜利。而后初始化。胜利后将 b 放入一级缓存。这个时候 a 在给本人属性 b 设置值的时候就找到了 b,而后设置 b。实现属性设置,再初始化,初始化后 a 放入一级缓存。
二 为什么要应用三级缓存
解决代理对象(如 aop)循环依赖的问题。
例:a 依赖 b,b 依赖 a,同时 a,b 都被 aop 加强。
首先明确 aop 的实现是通过 postBeanProcess 后置处理器,在初始化之后做代理操作的。
为什么应用三级缓存起因:
1 只应用二级缓存,且二级缓存缓存的是一个不残缺的 bean
如果只应用二级缓存,且二级缓存缓存的是一个不残缺的 bean,这个时候 a 在设置属性的过程中去获取 b(这个时候 a 还没有被 aop 的后置处理器加强),创立 b 的过程中,b 依赖 a,b 去缓存中拿 a 拿到的是没有通过代理的 a。就有问题。
2 应用二级缓存,且二级缓存是一个工厂办法的缓存
如果二级缓存是一个工厂的缓存,在从缓存中获取的时候获取到通过 aop 加强的对象。能够看到从工厂缓存中获取的逻辑。
protected ObjectgetEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bpinstanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp =
(SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
a 依赖 b,b 依赖 a,c。c 又依赖 a。a,b,c 均 aop 加强。
加载开始:a 实例化,放入工厂缓存,设置 b,b 实例化,设置属性,拿到 a, 此时从工厂缓存中拿到代理后的 a。因为 a 没加载结束,不会放入一级缓存。这个时候 b 开始设置 c,c 实例化,设置属性 a, 又去工厂缓存中拿对象 a。这个时候拿到的 a 和 b 从工厂缓存不是一个对象。呈现问题。
3 应用二级缓存,二级缓存缓存的是加强后的 bean。这个与 spring 加载流程不合乎。spring 加载流程是:实例化,设置属性,初始化,加强。在有循环援用的时候,之前的 bean 并不会加强后放入到二级缓存。
综上 1,2,3 可知二级缓存解决不了有 aop 的循环依赖。spring 采纳了三级缓存。
三 spring 的三级缓存
一级缓存 singletonObjects 缓存加载实现的 bean。
二级缓存 earlySingletonObjects 缓存从三级缓存中获取到的 bean,此时外面的 bean 没有加载结束。
三级缓存 singletonFactories。缓存一个 objectFactory 工厂。
场景:a 依赖 b,b 依赖 a 和 c,c 依赖 a。并且 a,b,c 都 aop 加强。
加载过程:
a 实例化,放入三级工厂缓存,设置属性 b,b 实例化放入三级缓存。b 设置属性 a,从三级工厂缓存中获取代理后的对象 a,同时,代理后的 a 放入二级缓存,而后设置属性 c,c 实例化放入三级缓存,设置属性 a, 此时从二级缓存中获取到的代理后的 a 跟 b 中的 a 是一个对象,属性 a 设置胜利。c 初始化,而后执行后置处理器。进行 aop 的加强。加强后将代理的 c 放入到一级缓存,同时删除三级缓存中的 c。c 加载实现,b 失去 c,b 设置 c 胜利。b 初始化,而后执行后置处理器,进行 aop 加强,将加强后的代理对象 b 放入到一级缓存。删除三级缓存中的 b。此时 a 拿到 b,设置属性 b 胜利,开始初始化,初始化后执行后置处理器。在 aop 的后置处理器中有一个以 beanName 为 key,通过 aop 加强的代理对象为 value 的 map earlyProxyReferences。
这个时候 后置处理器解决对象 a 的时候,
public ObjectpostProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean !=null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
也就是 发现这个 beanName 曾经被代理后就不在代理。这个时候执行后置处理器后,a 还是未经代理的对象 a。此时 a 再通过 getSingleton 从新从缓存中获取一下 a。
Object earlySingletonReference = getSingleton(beanName, false);
false 示意不从三级缓存中取,只从一级,二级缓存中获取。
这个时候能拿到二级缓存中的 a。二级缓存中的 a 也是通过代理后的 a。
而后将代理后的 a 放入到一级缓存中。a 加载结束。
放入一级缓存的过程:
addSingleton(beanName, singletonObject);
从三级工厂缓存中获取对象:
protected ObjectgetEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bpinstanceof SmartInstantiationAwareBeanPostProcessor) {SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
其中 AbstractAutoProxyCreator 实现该接口。
public ObjectgetEarlyBeanReference(Object bean, String beanName) {Object cacheKey = getCacheKey(bean.getClass(), beanName);
this.earlyProxyReferences.put(cacheKey, bean);
return wrapIfNecessary(bean, beanName, cacheKey);
}
wrapIfNecessary()就是真正执行代理的。
bean 初始化之后执行的后置处理器:
其中 AbstractAutoProxyCreator 实现了该接口。