Spring源碼學習(五):Bean的創建和獲取

目錄

1.獲取Bean單例實例

2.完整創建Bean

2.1 Bean創建的前置處理

2.2 創建Bean:doCreateBean的createBeanInstance方法

2.2.1 通過Supplier實例化 —— obtainFromSupplier

2.2.2 通過factory-method實例化 —— instantiateUsingFactoryMethod

2.2.3 自動綁定構造函數 —— autowireConstructor

2.2.4 普通Bean的實例化 —— instantiateBean

2.3 Bean創建後的後處理:doCreateBean的剩餘部分

2.3.1 調用PostProcessor

2.3.2 提前暴露

2.3.3 屬性填充

2.2.4 Bean的初始化

2.3.5 繼續處理提前暴露

2.3.6 Bean轉化爲DisposableBean

3.doGetBean的後續操作


當ApplicationContext完成refresh之後,容器就已經讀取並解析了所有的Bean定義,安裝了設定的擴展,並且對需要提前實例化的Bean創建了單例。這之後就可以獲取XML中配置的Bean了,獲取Bean的方法是容器的getBean()方法,實際調用了AbstractBeanFactory的doGetBean方法。

1.獲取Bean單例實例

在容器擴展結束後,實際上已經對非懶加載、scope爲“singleton”的Bean進行過實例化了,如果此時需要獲取的Bean已經實例化,那麼直接返回就可以,不需要重新實例化。

String beanName = this.transformedBeanName(name);
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
    if (this.logger.isTraceEnabled()) {
        if (this.isSingletonCurrentlyInCreation(beanName)) {
            this.logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
        } else {
            this.logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
        }
    }
    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
}

transformedBeanName是將傳入的名稱通過在aliasMap中查找的方式,轉換爲BeanName。

getSingleton就是根據BeanName,嘗試從存儲Bean單例實例的Map中取出實例對象,假如單例對象不存在,或者正在創建,那麼就嘗試獲取單例工廠,併產生單例對象:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        synchronized(this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

earlySingletonObjects和singletonObjects的不同之處在於,前者包含了還處在創建過程中的單例對象,主要是用來防止循環依賴。只有當兩個單例列表中都沒有要找到Bean時,纔會嘗試創建一個。

緊接着,容器嘗試從Bean實例中獲取對象,之所以是獲取對象而不是直接返回實例,從源碼中就能看出原因:

    protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(this.transformedBeanName(name), beanInstance.getClass());
            }
        }
        if (beanInstance instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
            Object object = null;
            if (mbd == null) {
                object = this.getCachedObjectForFactoryBean(beanName);
            }
            if (object == null) {
                FactoryBean<?> factory = (FactoryBean)beanInstance;
                if (mbd == null && this.containsBeanDefinition(beanName)) {
                    mbd = this.getMergedLocalBeanDefinition(beanName);
                }
                boolean synthetic = mbd != null && mbd.isSynthetic();
                object = this.getObjectFromFactoryBean(factory, beanName, !synthetic);
            }
            return object;
        } else {
            return beanInstance;
        }
    }

原因就在於,Bean有兩種,普通的Bean當然可以直接返回實例,但是對於FactoryBean,它是用來產生其他對象的,直接返回實例一般而言沒有什麼用,所以在這裏需要進行判斷。isFactoryDereference方法用來檢測Bean名稱是否以"&"開頭,假如一個Bean不是FactoryBean卻又以"&"開頭,那麼就是配置有問題,當然不能進行實例化。假如一個Bean是FactoryBean,且不以"&"開頭,則說明用戶想要它產生一個對象,則先嚐試從緩存獲取FactoryBean,否則用傳入的Bean創建實例。由於傳入的mbd是空,所以會觸發getMergedLocalBeanDefinition方法,將本容器中名稱爲beanName的GenericBeanDefinition轉換爲RootBeanDefinition,假如要轉換的是個子元素,則與父元素的相關屬性進行合併。isSynthetic方法用於判斷RootBeanDefinition是不是用戶定義的。

getObjectForBeanInstance進行了一些判斷,然後將核心邏輯交給了getObjectFromFactoryBean處理,它首先判斷了傳入的Bean是否是單例模式以及單例列表中是否有該Bean,如果答案全部都是true,則需要驗證是不是已經創建過實例了,是則直接返回,否則嘗試創建實例。實例創建成功後,還會根據是否需要後處理,執行相應方法:

synchronized(this.getSingletonMutex()) {
    Object object = this.factoryBeanObjectCache.get(beanName);
    if (object == null) {
        object = this.doGetObjectFromFactoryBean(factory, beanName);
        Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
        if (alreadyThere != null) {
            object = alreadyThere;
        } else {
            if (shouldPostProcess) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    return object;
                }
                this.beforeSingletonCreation(beanName);
                try {
                    object = this.postProcessObjectFromFactoryBean(object, beanName);
                } catch (Throwable var14) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's singleton object failed", var14);
                } finally {
                    this.afterSingletonCreation(beanName);
                }
           }
           if (this.containsSingleton(beanName)) {
               this.factoryBeanObjectCache.put(beanName, object);
           }
        }
    }
    return object;
}

假如判斷有false,那麼就簡單了,由於沒有限定Bean必須是單例,直接嘗試讓Factory產生對象即可。可以看到,這個方法又是進行了一些判斷和後處理,核心邏輯又被委託給了doGetObjectFromFactoryBean,這次在代碼中調用了factory.getObject()來產生對象。

2.完整創建Bean

2.1 Bean創建的前置處理

假如上一步獲取單例實例時,單例列表中還沒有需要的Bean的實例,說明待獲取的Bean,要麼其scope是prototype,要麼它設置了lazy-init爲true,即需要在使用時創建。代碼首先判斷了Bean是否正在創建,如果沒有,則會檢查當前BeanFactory是否包含需要創建的Bean定義,不包含則委託給父工廠創建,包含則自己創建。然後就會獲取待創建Bean的RootBeanDefinition,並處理依賴關係:

RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null) {
    var11 = dependsOn;
    int var12 = dependsOn.length;
    for(int var13 = 0; var13 < var12; ++var13) {
        String dep = var11[var13];
        if (this.isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
         this.registerDependentBean(dep, beanName);
         try {
             this.getBean(dep);
         } catch (NoSuchBeanDefinitionException var24) {
             throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
         }
    }
}

getMergedLocalBeanDefinition上面有提到,作用是讓子Bean元素繼承父元素的屬性;checkMergedBeanDefinition的作用是檢查Bean是否是抽象的;dependsOn指的是由depends-on屬性配置依賴的Bean,這些被依賴的Bean肯定是優先進行實例化的。處理依賴Bean時,首先檢查了是否存在循環依賴,然後對Bean及其依賴註冊依賴關係,最後嘗試獲取被依賴的Bean(如果被依賴的Bean還沒初始化,會在這一步進行),假如該Bean不存在,則拋出異常。

接下來,開始根據Bean的不同scope採用不同的實例化方式,首先是單例Bean:

if (mbd.isSingleton()) {
    sharedInstance = this.getSingleton(beanName, () -> {
        try {
            return this.createBean(beanName, mbd, args);
        } catch (BeansException var5) {
            this.destroySingleton(beanName);
            throw var5;
        }    
    });
    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

核心方法就是createBean和getObjectForBeanInstance,後者已經見過了,主要看下前者,把日誌、try-catch塊都去掉,核心代碼如下:

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        RootBeanDefinition mbdToUse = mbd;
        Class<?> resolvedClass = this.resolveBeanClass(mbd, beanName, new Class[0]);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }
        mbdToUse.prepareMethodOverrides();
        Object beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
        if (beanInstance != null) {
            return beanInstance;
        }
        return this.doCreateBean(beanName, mbdToUse, args);
    }

首先將beanName解析爲Class對象,如有必要則賦給RootBeanDefinition對象,然後在prepareMethodOverrides方法中處理lookup-method和replace-method屬性,在該方法中,檢查了Bean類定義中,指定的覆蓋方法的個數,並標記MethodOverride的overloaded屬性,假如該屬性爲true,則實例化的時候會爲這個Bean動態生成代理並進行增強處理。之後的resolveBeforeInstantiation就是在實例化前做些前置處理,實際調用了兩個方法:applyBeanPostProcessorsBeforeInstantiation、applyBeanPostProcessorsAfterInitialization,前者是在AbstractBeanDefinition轉換爲BeanWrapper前最後一次可以修改BeanDefinition的機會,會調用PostProcessor對Bean進行處理:

    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
	}

後者的邏輯和applyBeanPostProcessorsBeforeInstantiation相似,只是變成調用BeanPostProcessor的postProcessAfterInitialization方法。

2.2 創建Bean:doCreateBean的createBeanInstance方法

接下來,就是真正創建Bean的doCreateBean方法。首先是將Bean轉化爲BeanWrapper,對於單例Bean,需要先從實例緩存中移除已有實例,否則(或者緩存裏沒有已有實例)創建一個新實例:

BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
	instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
	mbd.resolvedTargetType = beanType;
}

可以看到,其核心方法是createBeanInstance方法。下面對其進行介紹。

首先處理了兩種工廠式Bean,前者直接獲取Supplier對象產生實例,後者通過配置的工廠方法產生目標對象:

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
	return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
	return instantiateUsingFactoryMethod(beanName, mbd, args);
}

2.2.1 通過Supplier實例化 —— obtainFromSupplier

首先了解下Supplier,該接口在Spring中的默認實現只有一個,即SingletonSupplier,核心方法爲get,實際調用了內部包含的instanceSupplier或defaultSupplier的get方法創建實例。其用途是,可以用factory-method方法或者構造方法構建,構建時會包含一個實例或一到兩個Supplier,需要獲取實例時,採用double-check的方式返回內部存儲的實例,從而保持單例性。

關鍵方法就三個:Supplier的get方法、BeanWrapperImpl的構造方法、initBeanWrapper方法。get方法上面介紹過了,對於剩下的兩個方法。前者直接調用了父類構造方法,代碼如下,就是進行一些屬性的設置,TypeConverterDelegate顧名思義,是用來進行類型轉換的:

protected AbstractNestablePropertyAccessor(Object object) {
	registerDefaultEditors();
	setWrappedInstance(object);
}

protected void registerDefaultEditors() {
	this.defaultEditorsActive = true;
}

public void setWrappedInstance(Object object, @Nullable String nestedPath, @Nullable Object rootObject) {
	this.wrappedObject = ObjectUtils.unwrapOptional(object);
	Assert.notNull(this.wrappedObject, "Target object must not be null");
	this.nestedPath = (nestedPath != null ? nestedPath : "");
	this.rootObject = (!this.nestedPath.isEmpty() ? rootObject : this.wrappedObject);
	this.nestedPropertyAccessors = null;
	this.typeConverterDelegate = new TypeConverterDelegate(this, this.wrappedObject);
}

initBeanWrapper處,爲剛剛生成的BeanWrapper對象設置了ConversionService,並使用容器中註冊的CustomEditor配置BeanWrapper:

protected void initBeanWrapper(BeanWrapper bw) {
	bw.setConversionService(getConversionService());
	registerCustomEditors(bw);
}

容器的ConversionService和registerCustomEditors都已經已經很熟悉了,BeanWrapper的呢?看下源碼,果然就是把容器的相關屬性賦給BeanWrapper

protected void registerCustomEditors(PropertyEditorRegistry registry) {
	PropertyEditorRegistrySupport registrySupport = (registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
	if (registrySupport != null) {
		registrySupport.useConfigValueEditors();
	}
	if (!this.propertyEditorRegistrars.isEmpty()) {
		for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
			registrar.registerCustomEditors(registry);
		}
	}
	if (!this.customEditors.isEmpty()) {
		this.customEditors.forEach((requiredType, editorClass) ->
				registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass)));
	}
}

2.2.2 通過factory-method實例化 —— instantiateUsingFactoryMethod

此處可以看出,要初始化的並不是FactoryBean的實現類的getObject方法,而是配置了factory-method、factory-bean屬性的Bean的方法,因此,其開頭部分和obtainFromSupplier一致,但是接下來就有很多額外的檢驗和處理,首先是對factory-bean的的處理:

//和obtainFromSupplier一致
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);

//對Bean進行一定的校驗
String factoryBeanName = mbd.getFactoryBeanName();
Object factoryBean;
Class factoryClass;
boolean isStatic;
//如果配置了factory-bean
if (factoryBeanName != null) {
    //防止出現迴環
    if (factoryBeanName.equals(beanName)) {
        throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "factory-bean reference points back to the same bean definition");
    }
    //防止創建重複實例,破壞單例性
    factoryBean = this.beanFactory.getBean(factoryBeanName);
    if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
        throw new ImplicitlyAppearedSingletonException();
    }
    factoryClass = factoryBean.getClass();
    isStatic = false;
} else {
    if (!mbd.hasBeanClass()) {
        throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName, "bean definition declares neither a bean class nor a factory-bean reference");
    }
    factoryBean = null;
    factoryClass = mbd.getBeanClass();
    isStatic = true;
}

接下來對factory-method進行處理,如果沒有可用的factory-method配置,或者沒有配置參數,就需要進行方法匹配,由於方法很可能存在重載版本,所以需要先解析配置的參數列表,以確定要調用哪個版本的重載方法:

Method factoryMethodToUse = null;
ConstructorResolver.ArgumentsHolder argsHolderToUse = null;
Object[] argsToUse = null;
if (explicitArgs != null) {
    argsToUse = explicitArgs;
} else {
    Object[] argsToResolve = null;
    synchronized(mbd.constructorArgumentLock) {
        factoryMethodToUse = (Method)mbd.resolvedConstructorOrFactoryMethod;
        if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
            argsToUse = mbd.resolvedConstructorArguments;
            if (argsToUse == null) {
                argsToResolve = mbd.preparedConstructorArguments;
            }
        }
    }
    if (argsToResolve != null) {
        argsToUse = this.resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
    }
}

resolvePreparedArguments根據參數類型,分別採用不同的方法處理,在有必要時,用BeanWrapper的TypeConverter進行參數類型轉換:

if (argValue instanceof ConstructorResolver.AutowiredArgumentMarker) {
    argValue = this.resolveAutowiredArgument(methodParam, beanName, (Set)null, (TypeConverter)converter, fallback);
} else if (argValue instanceof BeanMetadataElement) {
    argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
} else if (argValue instanceof String) {
     argValue = this.beanFactory.evaluateBeanDefinitionString((String)argValue, mbd);
}
resolvedArgs[argIndex] = ((TypeConverter)converter).convertIfNecessary(argValue, paramType, methodParam);

然後就可以根據解析出來的參數列表找到匹配的方法重載版本了。匹配方法有以下情形:

  • 方法沒有重載版本,未配置參數,且方法參數列表長度爲0,則直接實例化幷包裝進BeanWrapper並返回
  • 方法有重載版本,則分析方法各版本參數列表的差異,取差異度最小的版本,實例化幷包裝進BeanWrapper並返回

在代碼中也可以看到,factory-method屬性對應的方法返回類型不能爲void。

實例化的關鍵方法是instantiate方法,它調用了容器設置的實例化策略進行實例化,對於DefaultListableBeanFactory,其使用CGLib進行實例化:

private InstantiationStrategy instantiationStrategy = new CglibSubclassingInstantiationStrategy();

CglibSubclassingInstantiationStrategy繼承自SimpleInstantiationStrategy,調用BeanUtils.instantiateClass方法進行實例創建,實際上藉助了反射機制調用方法。

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,@Nullable Object factoryBean, final Method factoryMethod, Object... args) {
    ...
    Object result = factoryMethod.invoke(factoryBean, args);
    ...
}

2.2.3 自動綁定構造函數 —— autowireConstructor

調用該方法有以下情形:

  • RootBeanDefinition的構造函數參數已經解析過了,即具備找到合適構造方法的條件
  • 藉助PostProcessor決定了需要綁定的構造函數
  • 沒有更高優先度的構造方法

對於第二種情形,源碼如下,實際就是遍歷並找到SmartInstantiationAwareBeanPostProcessor實例,由它來決定候選的構造函數列表:

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName) throws BeansException {
    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
	    for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
				Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
				if (ctors != null) {
					return ctors;
				}
			}
		}
	}
	return null;
}

 不過上面提到的SmartInstantiationAwareBeanPostProcessor默認沒有配置,即其結果一般是null,所以就要根據auto-wire屬性來判斷自動裝配模式:

ctors = mbd.getPreferredConstructors();
if (ctors != null) {
	return autowireConstructor(beanName, mbd, ctors, null);
}

 autowire共有以下幾種可選項:

  • no: 默認項,即不進行自動裝配,只能通過ref屬性引用其它bean。
  • byName: 在容器中根據BeanName進行查找並裝配。
  • byType: 在容器中根據Bean的類型進行查找並裝配。
  • constructor: 以byType的方式查找bean的構造參數列表。
  • default: 使用父元素的配置。

現在可以來看autowireConstructor的內容了。它調用了ConstructorResolver的同名方法,整體邏輯和instantiateUsingFactoryMethod很相似。該方法主要做了以下幾件事:

  • 從緩存中讀取構造函數參數,或者直接使用給定的參數
  • 從緩存中讀取構造函數對象
  • 轉換參數類型
  • (假如緩存中沒有構造函數及參數實例)解析配置文件,確定候選構造函數對象列表及配置文件中的參數列表,然後根據參數對構造函數進行匹配,尋找最接近的一個
  • 實例化對象

和instantiateUsingFactoryMethod一樣,方法開頭也創建了BeanWrapper對象並進行初始化。然後根據情況確定將要使用的參數列表。優先使用getBean時傳入的參數,否則從緩存讀取構造函數對象和參數列表,並根據構造函數需求進行參數轉換:

if (explicitArgs != null) {
	argsToUse = explicitArgs;
}
else {
	Object[] argsToResolve = null;
	synchronized (mbd.constructorArgumentLock) {
		constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
		if (constructorToUse != null && mbd.constructorArgumentsResolved) {
			// Found a cached constructor...
			argsToUse = mbd.resolvedConstructorArguments;
			if (argsToUse == null) {
				argsToResolve = mbd.preparedConstructorArguments;
			}
	    }
	}
	if (argsToResolve != null) {
		argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve, true);
	}
}

resolvePreparedArguments調用了容器中註冊的TypeConverter進行參數類型轉換,假如參數中有其它Bean,即存在依賴關係,則調用了BeanFactory的resolveDependency方法進行處理。該方法會在下面詳細介紹。

假如緩存中已經有想要的一切原料,則可以直接進行實例化,否則還需要進一步解析。首先是解析候選的Constructor對象,如果有通過參數傳入,就直接使用,否則從Bean的定義中讀取:

Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
	Class<?> beanClass = mbd.getBeanClass();
	candidates = (mbd.isNonPublicAccessAllowed() ?
		beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}

假如得到的候選構造函數就一個,並且Bean定義的構造函數參數列表及傳入的參數列表長度都爲1,則直接實例化,並存入緩存:

if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
	Constructor<?> uniqueCandidate = candidates[0];
	if (uniqueCandidate.getParameterCount() == 0) {
		synchronized (mbd.constructorArgumentLock) {
			mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
			mbd.constructorArgumentsResolved = true;
			mbd.resolvedConstructorArguments = EMPTY_ARGS;
	    }
		bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
		return bw;
	}
}

否則就需要解析每個構造函數,並進行排序和篩選,排序的標準是,優先public,同優先級構造函數根據參數列表長度降序排序(使用Arrays.sort,傳入自定義比較器進行排序):

private static final Comparator<Executable> EXECUTABLE_COMPARATOR = (e1, e2) -> {
    boolean p1 = Modifier.isPublic(e1.getModifiers());
	boolean p2 = Modifier.isPublic(e2.getModifiers());
	if (p1 != p2) {
		return (p1 ? -1 : 1);
	}
	int c1pl = e1.getParameterCount();
	int c2pl = e2.getParameterCount();
	return Integer.compare(c2pl, c1pl);
};

篩選的標準,首先是長度,比Bean定義中的長度,或者傳入參數列表的長度還小,肯定是要跳過的:

if (paramTypes.length < minNrOfArgs) {
	continue;
}

然後將getBean傳入的explicitArgs對象,或者解析構造函數時生成的resolvedValues對象封裝進ArgumentsHolder裏,並比較當前遍歷到的構造函數的參數列表長度、參數類型,與給定特徵的差異,選取差異最小的一對 構造函數-參數,進行實例化並存入緩存:

int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
	argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
if (typeDiffWeight < minTypeDiffWeight) {
    constructorToUse = candidate;
	argsHolderToUse = argsHolder;
	argsToUse = argsHolder.arguments;
	minTypeDiffWeight = typeDiffWeight;
	ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
	if (ambiguousConstructors == null) {
		ambiguousConstructors = new LinkedHashSet<>();
		ambiguousConstructors.add(constructorToUse);
	}
	ambiguousConstructors.add(candidate);
}
...
if (explicitArgs == null && argsHolderToUse != null) {
	argsHolderToUse.storeCache(mbd, constructorToUse);
}

如果一番比較之下,沒有一個構造函數滿足需求,則拋出異常。

2.2.4 普通Bean的實例化 —— instantiateBean

以上三小節都是些特殊情形,對於普通的Bean,既沒有工廠方法,也沒有帶參構造函數,Spring提供了instantiateBean方法來直接實例化。該方法實際上還是調用了SimpleInstantiationStrategy.instantiate方法,這次則是三參數版本。

到這裏,createBeanInstance就執行完畢了。

2.3 Bean創建後的後處理:doCreateBean的剩餘部分

createBeanInstance執行後,Bean實際上已經實例化了,不過假如程序員配置了一些後處理器等,會在此時生效,對Bean進行處理。

2.3.1 調用PostProcessor

首先是使用註冊到容器的PostProcessor處理Bean。applyMergedBeanDefinitionPostProcessors的邏輯就是遍歷後處理器列表,調用MergedBeanDefinitionPostProcessor類型後處理器的postProcessMergedBeanDefinition方法:

synchronized (mbd.postProcessingLock) {
    if (!mbd.postProcessed) {
	    try {
		    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
	    }
	    catch (Throwable ex) {
		    throw new BeanCreationException(mbd.getResourceDescription(), beanName,
			    "Post-processing of merged bean definition failed", ex);
	    }
	    mbd.postProcessed = true;
    }
}

2.3.2 提前暴露

接下來,需要檢查是否需要提前暴露當前正在創建的Bean,在本篇第一節提到,earlySingletonObjects存儲了正在創建中的單例Bean,用來解決循環依賴問題,當被依賴的Bean執行完createBeanInstance後,就可以從earlySingletonObjects中移除:

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
	isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
	addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

// in DefaultSingletonBeanRegistry.java
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);
		}
	}
}

earlySingletonExposure的三個條件,第一個和第三個不用多說,第二個只能通過AbstractRefreshableApplicationContext的setAllowCircularReferences()方法進行配置。addSingletonFactory最重要的作用是,記錄了創建Bean的ObjectFactory。它的作用在屬性填充時再解釋。

然後再看下getEarlyBeanReference,該函數主要是調用SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference方法:

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;
}

該接口的一個用途是完成Advice的織入,在該接口的實現類AbstractAutoProxyCreator中,有如下代碼:

// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
	this.advisedBeans.put(cacheKey, Boolean.TRUE);
	Object proxy = createProxy(
			bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
	this.proxyTypes.put(cacheKey, proxy.getClass());
	return proxy;
}

不過此時還不能添加到singletonObjects列表中,因爲新創建的Bean還需要初始化:

Object exposedObject = bean;
try {
	populateBean(beanName, mbd, instanceWrapper);
	exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
    ...
}

2.3.3 屬性填充

populateBean對Bean實例進行屬性填充,利用到了RootBeanDefinition中註冊的屬性。首先進行一次判斷,假如傳入的BeanWrapper是null,則無需進行填充。一般來說都不會出現這個情況,那麼接着往下看。

在屬性被賦給BeanWrapper前,還有一次通過InstantiationAwareBeanPostProcessor修改Bean的機會:

boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
				continueWithPropertyPopulation = false;
				break;
			}
		}
	}
}
if (!continueWithPropertyPopulation) {
	return;
}

postProcessAfterInstantiation返回了布爾值,這裏用於判斷是否繼續進行屬性設置,如果返回false,則會在後處理器生效後直接退出屬性填充步驟。否則開始進行屬性填充,首先是根據autowire類型,提取依賴的Bean並存入PropertyValues中:

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
	MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
	// Add property values based on autowire by name if applicable.
	if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
		autowireByName(beanName, mbd, bw, newPvs);
	}
	// Add property values based on autowire by type if applicable.
	if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
		autowireByType(beanName, mbd, bw, newPvs);
	}
	pvs = newPvs;
}

上面提到,autowire的默認值是no,不過還是看一下name和type的效果。

1)autowireByName:

首先是autowireByName:

protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		if (containsBean(propertyName)) {
			Object bean = getBean(propertyName);
			pvs.add(propertyName, bean);
			registerDependentBean(propertyName, beanName);
		}
	}
}

這裏通過遍歷尋找BeanWrapper中需要依賴注入的屬性,通過getBean獲取,通過registerDependentBean註冊依賴。將此處與doGetBean的getSingleton方法和addSingletonFactory方法結合來看,就清楚addSingletonFactory的作用了:當出現循環依賴時,由於populateBean調用了getBean,就可以獲取ObjectFactory,由它產生對象實例,而非完整生成一遍實例,這樣就避免了無限遞歸的出現。

2)autowireByType:

然後來看autowireByType,它的大體框架和autowireByName還是比較類似的,也是通過unsatisfiedNonSimpleProperties獲取需要注入的屬性,然後逐個注入,不同之處在於,這裏不是通過名稱直接getBean注入,而是通過類型匹配尋找Bean:

protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
		converter = bw;
	}
	Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		try {
			PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
			if (Object.class != pd.getPropertyType()) {
				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
				boolean eager = !PriorityOrdered.class.isInstance(bw.getWrappedInstance());
				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
				if (autowiredArgument != null) {
					pvs.add(propertyName, autowiredArgument);
				}
				for (String autowiredBeanName : autowiredBeanNames) {
					registerDependentBean(autowiredBeanName, beanName);
				}
				autowiredBeanNames.clear();
			}
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
		}
	}
}

getWriteMethodParameter解析了setter方法的參數,並封裝爲DependencyDescriptor,然後傳入resolveDependency方法以獲取注入參數。該方法在autowireConstructor也遇到過,這裏詳細介紹一下。

3)doResolveDependency:

該方法位於DefaultListableBeanFactory,首先對Optional、ObjectFactory、javaxInjectProviderClass三種特殊類型進行了處理,分別返回了一種BeanObjectProvider,不過歸根結底,還是調用了doResolveDependency方法。該方法首尾兩端分別設置了一個注入點,然後嘗試獲取Shortcut,所謂Shortcut,其實就是緩存了的屬性或對象,查看ShortcutDependencyDescriptor源碼發現,這裏實際還是調用了getBean方法:

Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
	return shortcut;
}

假如不存在Shortcut,即依賴還沒有解析過,就需要進行解析。首先根據AutowireCandidateResolver的getSuggestedValue方法獲取值,AutowireCandidateResolver在容器中的默認實現是SimpleAutowireCandidateResolver,它在此方法中返回null,不過AutowireCandidateResolver的另一個實現類QualifierAnnotationAutowireCandidateResolver,爲Spring提供了通過@Value設置值的能力:

protected Object extractValue(AnnotationAttributes attr) {
	Object value = attr.get(AnnotationUtils.VALUE);
	if (value == null) {
		throw new IllegalStateException("Value annotation must have a value attribute");
	}
	return value;
}

假如getSuggestedValue返回值value不爲空且爲String類型,就可以用來判斷是否包含在BeanDefinition中,是則解析爲一個Expression對象。不過無論如何,都會在有必要的情況下嘗試對value進行類型轉換:

Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
	if (value instanceof String) {
		String strVal = resolveEmbeddedValue((String) value);
		BeanDefinition bd = (beanName != null && containsBean(beanName) ?
			getMergedBeanDefinition(beanName) : null);
		value = evaluateBeanDefinitionString(strVal, bd);
	}
	TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
	try {
		return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
	}
	catch (UnsupportedOperationException ex) {
		// A custom TypeConverter which does not support TypeDescriptor resolution...
		return (descriptor.getField() != null ?
			converter.convertIfNecessary(value, type, descriptor.getField()) :
			converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
	}
}

假如value爲空,也就是默認情況,或者沒有配置@Value,則調用resolveMultipleBean對集合Bean進行解析,這裏根據依賴類型分爲不同分支,首先是stream類型的處理,這裏挑選出了類型匹配的自動注入對象,通過它們的BeanName進行getBean,然後挑選出不是NullBean類型的實例:

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (autowiredBeanNames != null) {
	autowiredBeanNames.addAll(matchingBeans.keySet());
}
Stream<Object> stream = matchingBeans.keySet().stream()
		.map(name -> descriptor.resolveCandidate(name, type, this))
		.filter(bean -> !(bean instanceof NullBean));
if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
	stream = stream.sorted(adaptOrderComparator(matchingBeans));
}
return stream;

接下來是數組類型,這裏對數組類型進行了解析,並以此獲取自動注入的候選,然後調用類型轉換器將數組轉換爲實際類型並排序:

Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve(type);
if (resolvedArrayType != type) {
	componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
	return null;
}
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
	new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
	return null;
}
if (autowiredBeanNames != null) {
	autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
if (result instanceof Object[]) {
	Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
    if (comparator != null) {
		Arrays.sort((Object[]) result, comparator);
	}
}
return result;

接下來的集合類型、Map類型就和數組類型比較像了,都是解析出泛型類型,然後進行類型匹配,尋找自動注入候選,只不過集合類型會對List實現類做一次排序,Map類型就沒有這個過程。

通過上述源碼,也解釋了一個問題:resolveDependency用到了一個參數autowiredBeanNames,這裏既然是靠類型匹配,爲什麼還需要名稱?原來是依靠它解決泛型集合的類型匹配問題。

如果需要解析的複合類型,不是Stream、數組、集合、Map中的任何一種,則不考慮泛型,直接使用findAutowireCandidates根據類型匹配。假如匹配結果不唯一,還需要再進行篩選,否則經過驗證就可以實例化、返回了。篩選標準有三:最優先的是primary屬性爲true的Bean,然後是優先級高的Bean(通過@Priority註解配置),最後是BeanName符合依賴描述的。假如經過篩選,仍然有多個Bean有着同樣的優先度,則拋出異常。

4)應用PropertyValue

autowireByXX方法執行完後,實際已經完成了屬性到PropertyValue的轉換。在這之後,如果需要調用InstantiationAwareBeanPostProcessors或者進行依賴檢查,則進行相應調用。然後把處理完畢的PropertyValue傳入applyPropertyValues方法。

該方法的核心語句就一句:

bw.setPropertyValues(new MutablePropertyValues(deepCopy));

調用setter進行賦值,不過在此之前進行了一系列判斷和處理。

首先是防止重複轉換的判斷:

if (pvs instanceof MutablePropertyValues) {
	mpvs = (MutablePropertyValues) pvs;
	if (mpvs.isConverted()) {
		// Shortcut: use the pre-converted values as-is.
		try {
			bw.setPropertyValues(mpvs);
			return;
		}
		catch (BeansException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Error setting property valus", ex);
		}
	}
	original = mpvs.getPropertyValueList();
}
else {
	original = Arrays.asList(pvs.getPropertyValues());
}

如果沒有轉換過,則遍歷PropertyValue列表,使用TypeConverter和BeanDefinitionResolver進行值的解析和轉換。

2.2.4 Bean的初始化

在Bean屬性注入完畢後,就可以開始調用其init-method屬性配置的初始化方法了。這一步在initializeBean方法完成。

該方法調用的關鍵方法有四個:

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);
    wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    invokeInitMethods(beanName, wrappedBean, mbd);
    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    return wrappedBean;
}

1)invokeAwareMethods

在之前我們也有接觸過一些Aware接口的使用例子,例如 容器功能的擴展 中有看到EnvironmentAware、ResourceLoaderAware、ApplicationContextAware等接口的身影。Bean實現了Aware接口後,就可以通過setter方法獲取Spring容器的資源。

不過此處只處理了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三種接口的實現類:

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
	    if (bean instanceof BeanNameAware) {
	    	((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

2)applyBeanPostProcessorsBeforeInitialization / applyBeanPostProcessorsAfterInitialization

以Before爲例,實際就是遍歷BeanPostProcessor列表,逐個調用而已。

3)invokeAwareMethods

該方法調用了 invokeCustomInitMethod 方法,首先判斷了一下是否配置了init-method屬性,沒有則拋出異常:

String initMethodName = mbd.getInitMethodName();
Assert.state(initMethodName != null, "No init method set");
final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
		BeanUtils.findMethod(bean.getClass(), initMethodName) :
		ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
if (initMethod == null) {
	if (mbd.isEnforceInitMethod()) {
		throw new BeanDefinitionValidationException("Could not find an init method named '" +initMethodName + "' on bean with name '" + beanName + "'");
	}
}

有則通過Method的invoke方法反射調用:

initMethod.invoke(bean);

2.3.5 繼續處理提前暴露

假如之前經過判斷,需要提前暴露,那麼在Bean初始化完成後,就可以添加到earlySingletonObjects中,完成暴露了:

if (earlySingletonExposure) {
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        }
        else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
            for (String dependentBean : dependentBeans) {
                if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                    actualDependentBeans.add(dependentBean);
                }
            }
            if (!actualDependentBeans.isEmpty()) {
                throw new BeanCurrentlyInCreationException(beanName,
                    "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
             }
         }
    }
}

getSingleton方法將Bean添加到earlySingletonObjects中,並使用之前存儲的ObjectFactory返回一個實例。然後檢查實例在初始化方法中是否(通過BeanPostProcessor或自定義初始化方法)進行了增強(是否和原來的bean對象相同),如果沒有進行增強,就可以直接下一步,否則還是要檢查下依賴。

由於到這一步,Bean已經創建完畢,即屬性注入成功,說明依賴的Bean應該也創建完畢了,假如actualDependentBeans不爲空,說明還是有循環依賴情況,需要拋出異常。

2.3.6 Bean轉化爲DisposableBean

運行到這裏, 其實已經可以返回Bean了,不過Spring既然對初始化方法提供了擴展,肯定也對銷燬方法做了擴展。這一步就是爲了擴展銷燬方法的。

源碼本身並不複雜,如果Bean是prototype,本身是隨用隨創建,創建完畢後就不再管理,因此無需進行擴展,如果不需要擴展,那也沒必要繼續。

對於單例Bean,通過registerDisposableBean處理;對於其它scope的Bean,通過registerDestructionCallback處理。

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = System.getSecurityManager() != null ? this.getAccessControlContext() : null;
    if (!mbd.isPrototype() && this.requiresDestruction(bean, mbd)) {
        if (mbd.isSingleton()) {
            this.registerDisposableBean(beanName, new DisposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessors(), acc));
        } else {
            Scope scope = (Scope)this.scopes.get(mbd.getScope());
            if (scope == null) {
                throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
            }
            scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(bean, beanName, mbd, this.getBeanPostProcessors(), acc));
        }
    }
}

1)registerDisposableBean

實際就是把需要銷燬、實現了DisposableBean接口的Bean放進一個Map裏,Map中的Bean銷燬時,對其使用DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法。

public void registerDisposableBean(String beanName, DisposableBean bean) {
	synchronized (this.disposableBeans) {
		this.disposableBeans.put(beanName, bean);
	}
}

如果註冊了多個DestructionAwareBeanPostProcessor,則挑選參數最少的那個:

private Method findDestroyMethod(String name) {
    return (this.nonPublicAccessAllowed ?
        BeanUtils.findMethodWithMinimalParameters(this.bean.getClass(), name) :
        BeanUtils.findMethodWithMinimalParameters(this.bean.getClass().getMethods(), name));
}

2)registerDestructionCallback

這裏以ServletContextScope類的實現爲例,在該類中,有一個Map<String,Runnable>類型的成員變量destructionCallbacks,在registerDestructionCallback方法中,將傳入的DisposableBeanAdapter存入該Map中。

調用它的destroy方法時,會逐個調用Map元素的run方法(實際就是DisposableBeanAdapter.destroy()方法,邏輯同上):

public void destroy() {
    for (Runnable runnable : this.destructionCallbacks.values()) {
	    runnable.run();
	}
	this.destructionCallbacks.clear();
}

至此,createBean方法執行結束。

3.doGetBean的後續操作

對於單例Bean,接下來還有getObjectForBeanInstance方法,該方法在上面已經介紹過了。

對於prototype和其它scope的Bean,還有beforePrototypeCreation、afterPrototypeCreation兩個方法圍繞在createBean周圍,其實就是將PrototypeBean添加到正在創建隊列和從隊列移除。

最後,Spring再次檢查了創建的Bean的類型和實際需要的類型是否匹配:

if (requiredType != null && !requiredType.isInstance(bean)) {
    try {
	    T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
		if (convertedBean == null) {
			throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
		}
		return convertedBean;
	}
	catch (TypeMismatchException ex) {
		throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
	}
}
return (T) bean;

實際就是獲取一個TypeConverter進行一次轉換,通過查看TypeConverterDelegate的源碼,可以發現,它調用了ConversionService的convert方法進行轉換,如果convert方法無法轉換,就應當返回null,這樣Spring就能檢測到創建出來的Bean不符合需要,從而拋出異常。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章