代碼分析入口:
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
1.獲取bean
Object sharedInstance = getSingleton(beanName) 這個方法從單例緩存中獲取bean實例:
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//從緩存單例中獲取緩存
Object singletonObject = this.singletonObjects.get(beanName);
//如果緩存bean爲空,並且bean正在創建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 從 singletonFactories 中獲取對應的 ObjectFactory
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// ObjectFactory 不爲空,則創建 bean
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
getSingleton邏輯是很簡單的,先從singletonObjects中獲取,如果爲空並且當前bean正在創建,那麼從earlySingletonObjects中獲取。如果爲空並且允許提前創建,則從singletonFactories獲取ObjectFactory。如果不爲空則調用getObejct()創建bean,並緩存起來。分析一下三個緩存對象的作用。isSingletonCurrentlyIncreation方法主要是判斷這個bean是否處於創建過程中。
- singletonObject:存放的是單例的bean。即beanName ---> bean實例
- earlySingletonObjects:存放的也是單例的bean。但是earlySingletonObjects存放的是bean正在創建過程中的,在創建過程中如果bean允許提前創建則可以提前創建曝光給調用方,進而可以解決循環依賴的關鍵
- singletonFactories:存放的是ObjectFactory。即創建單例的bean的beanFactory
以上就是從緩存中獲取bean的過程,下面繼續
如果獲取的bean不爲null,並且args爲null那麼會走進getObjectForBeanInstance方法。
protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
// 如果是工廠類的引用 bean的name已&開頭
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
//如果不是FactoryBean類型 則拋出異常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}
// 到這裏 bean是一個正常的bean 或者是一個FactoryBean
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}
Object object = null;
if (mbd == null) {
// 若 BeanDefinition 爲 null,則從緩存中加載
object = getCachedObjectForFactoryBean(beanName);
}
// 若 object 依然爲空,則可以確認,beanInstance 一定是 FactoryBean
if (object == null) {
// Return bean instance from factory.
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
//類型轉換
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}
該方法的核心其實是getObjectFromFactoryBean方法。之前的方法主要還是進行校驗的:
- 如果bean的實例已&開頭,不是FactoryBean直接拋出異常,如果是NullBean直接返回。
- 如果bean不是FactoryBean,或者已&開頭,返回對應實例。
- 如果 BeanDefinition 爲空,則從 factoryBeanObjectCache 中加載,如果還是空,則可以斷定 beanInstance 一定是 FactoryBean 類型,則委託 getObjectFromFactoryBean
()
方法處理。
getObjectFromFactoryBean方法主要是獲取指定的bean的實例對象。對於FactoryBean類型的bean則委託給FactoryBeanRegistrySupport執行getObjectFromFactoryBean獲取對應的實例對象。
//這個方法全局是在確定bean要確定是全局單例的。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
//判斷是單例並且這個bean是存在的
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
//獲取緩存中指定的factoryBean
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
// 爲空,則從 FactoryBean 中獲取對象
object = doGetObjectFromFactoryBean(factory, beanName);
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
if (alreadyThere != null) {
object = alreadyThere;
}
else {
if (shouldPostProcess) {
if (isSingletonCurrentlyInCreation(beanName)) {
// Temporarily return non-post-processed object, not storing it yet..
return object;
}
//前置處理
beforeSingletonCreation(beanName);
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName,
"Post-processing of FactoryBean's singleton object failed", ex);
}
finally {
//後置處理
afterSingletonCreation(beanName);
}
}
if (containsSingleton(beanName)) {
this.factoryBeanObjectCache.put(beanName, object);
}
}
}
return object;
}
}
else {
//非單例模式獲取
Object object = doGetObjectFromFactoryBean(factory, beanName);
if (shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
}
}
return object;
}
}
- 若爲單例且單例 bean 緩存中存在 beanName,則進行後續處理(跳轉到下一步),否則則從 FactoryBean 中獲取 bean 實例對象,如果接受後置處理,則調用
postProcessObjectFromFactoryBean()
進行後置處理。 - 首先獲取鎖(其實我們在前面篇幅中發現了大量的同步鎖,鎖住的對象都是 this.singletonObjects, 主要是因爲在單例模式中必須要保證全局唯一),然後從 factoryBeanObjectCache 緩存中獲取實例對象 object,若 object 爲空,則調用
doGetObjectFromFactoryBean()
方法從 FactoryBean 獲取對象,其實內部就是調用FactoryBean.getObject()
。 - 如果需要後續處理,則進行進一步處理,步驟如下:
- 若該 bean 處於創建中(isSingletonCurrentlyInCreation),則返回非處理對象,而不是存儲它
- 調用
beforeSingletonCreation()
進行創建之前的處理。默認實現將該 bean 標誌爲當前創建的。 - 調用
postProcessObjectFromFactoryBean()
對從 FactoryBean 獲取的 bean 實例對象進行後置處理,默認實現是按照原樣直接返回,具體實現是在 AbstractAutowireCapableBeanFactory 中實現的,當然子類也可以重寫它,比如應用後置處理 - 調用
afterSingletonCreation()
進行創建 bean 之後的處理,默認實現是將該 bean 標記爲不再在創建中。
- 最後加入到 FactoryBeans 緩存中。
當中最重要的三個方法 beforeSingletonCreation(),postProcessObjectFromFactoryBean()
,afterSingletonCreation()
。
beforeSingletonCreation()方法:
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
主要是講即將要創建的bean緩存在singletonsCurrentlyInCreation表明這個bean正在創建。
afterSingletonCreation()方法:
protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}
主要是講即將要創建完畢的bean從singletonsCurrentlyInCreation中移除,表明這個bean已經創建完畢。
postProcessObjectFromFactoryBean()方法
postProcessObjectFromFactoryBean是對bean實例對象進行後置處理。其實現類
AbstractAutowireCapableBeanFactory進行應用的後置通知並返回bean實例。這個之後爲專門分析。
這篇博文分析了緩存中獲取bean對象的處理過程。