共计 3258 个字符,预计需要花费 9 分钟才能阅读完成。
三级缓存用于解决 Spring 循环依赖的问题,循环依赖呈现于 bean 的初始化环节,对于 bean 初始化能够参考 Bean 源码解析,以下从源码的角度剖析三级缓存的作用机理。
1. 源码位于 org.springframework.beans.factory.support
下的DefaultSingletonBeanRegistry
// 一级缓存,寄存齐全初始化的 bean | |
/** Cache of singleton objects: bean name to bean instance. */ | |
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); | |
// 二级缓存,寄存半成品 bean | |
/** Cache of early singleton objects: bean name to bean instance. */ | |
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); | |
// 三级缓存,寄存实例化的 bean | |
/** Cache of singleton factories: bean name to ObjectFactory. */ | |
private final Map<String, ObjectFactory<?>> 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> T doGetBean(final String name, @Nullable final Class<T> 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. | |
* <p>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,二级是为了效率,如果有多个循环依赖,间接从二级获取到加强的对象,不用二次加强。
正文完