目錄
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的剩餘部分
當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不符合需要,從而拋出異常。