创建对象的三级缓存介绍。
一、一级缓存singletonFactories如果是单例对象且可以提前暴露引用,则放入singletonFactories缓存中。
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" beanName
"' to allow for resolving potential circular references");
}
//ObjectFactory放入一级缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
getEarlyBeanReference因为会调用SmartInstantiationAwareBeanPostProcessor,可能会提前生成代理对象。
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
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);
}
}
}
如果B依赖A,A又依赖B,则在A创建的时候,会触发B对象的二级缓存创建。
在A依赖注入的时候,会触发doGetBean(B)
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//省略代码
return bean;
}
然后触发getSingleton(B), 我们看到singletonFactory.getObject()被调用,其实就是调用的getEarlyBeanReference方法,而且对象被放到了earlySingletonObjects缓存中,singletonFactories中的缓存被清除。
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
当对象完全构建好之后,放入到三级缓存中。
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
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);
}
}
只有单例对象可以放入到一级缓存singletonFactories中,存在循环依赖的时候,一级缓存清掉,得到的对象(可能提前生成代理对象)放入二级缓存earlySingletonObjects中。最终生成的完整对象放入三级缓存singletonObjects中,同时清除一级、二级缓存。
Spring 默认可以解决大部分循环依赖,但是还有一些场景无法解决,你遇到过吗,是什么原因?又是怎么解决的?我们后面再聊。
,