創建對象的三級緩存介紹。
一、一級緩存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 默認可以解決大部分循環依賴,但是還有一些場景無法解決,你遇到過嗎,是什麼原因?又是怎麼解決的?我們後面再聊。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!