三级缓存用于解决Spring循环依赖的问题,循环依赖出现于bean的初始化环节,关于bean初始化可以参考Bean源码解析,以下从源码的角度分析三级缓存的作用机理。
【三级缓存的简要源码解析】1.源码位于org.springframework.beans.factory.support
下的DefaultSingletonBeanRegistry
// 一级缓存,存放完全初始化的bean
/** Cache of singleton objects: bean name to bean instance. */
private final Map singletonObjects = new ConcurrentHashMap<>(256);
// 二级缓存,存放半成品bean
/** Cache of early singleton objects: bean name to bean instance. */
private final Map earlySingletonObjects = new HashMap<>(16);
// 三级缓存,存放实例化的bean
/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map> singletonFactories = new HashMap<>(16);
假设一个场景,A依赖B,B依赖A。
2.创建A对象,从
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
开始/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use when creating a bean instance using explicit arguments
* (only applied when creating a new instance as opposed to retrieving an existing one)
* @param typeCheckOnly whether the instance is obtained for a type check,
* not for actual use
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
@SuppressWarnings("unchecked")
protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
其中,首先会检查缓存中是否有对象
Object sharedInstance = getSingleton(beanName);
,如果有,就从缓存中取,bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
。3.然后看看
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
方法/**
* Return the (raw) singleton object registered under the given name.
* Checks already instantiated singletons and also allows for an early
* reference to a currently created singleton (resolving a circular reference).
* @param beanName the name of the bean to look for
* @param allowEarlyReference whether early references should be created or not
* @return the registered singleton object, or {@code null} if none found
*/
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
代码很简单,依次查询三级缓存,如果缓存中存在就直接返回,特别地,在第三级,如果获得了bean,就在第三级移除bean,在第二级添加。
所以到这里应该就结束了。
问题:二级缓存可不可以?
这个其实是设计的问题,设计之初认为AOP代理是在实例化完成后的行为,所以三级是为了处理AOP,二级是为了效率,如果有多个循环依赖,直接从二级获取到增强的对象,不必二次增强。