目錄
代碼塊1:resolveBeforeInstantiation
代碼塊2:applyBeanPostProcessorsBeforeInstantiation
代碼塊4.5:determineConstructorsFromBeanPostProcessors
代碼塊6:resolveConstructorArguments
代碼塊16:determineAutowireCandidate
代碼塊17:determinePrimaryCandidate
代碼塊18:determineHighestPriorityCandidate
Spring IoC源碼學習全系列
Spring IoC源碼學習:ApplicationContext 刷新前的配置
Spring IoC源碼學習:obtainFreshBeanFactory詳解
Spring IoC源碼學習:parseDefaultElement詳解
Spring IoC源碼學習:parseCustomElement詳解
Spring IoC源碼學習:obtainFreshBeanFactory詳解
Spring IoC源碼學習:invokeBeanFactoryPostProcessors詳解
Spring IoC源碼學習:registerBeanPostProcessors詳解
Spring IoC源碼學習:finishBeanFactoryInitialization詳解
Spring IoC源碼學習:createBean詳解(上)
Spring IoC源碼學習:createBean詳解(下)
Spring IoC源碼學習:finishRefresh 詳解
前言
接着 Spring IoC:getBean詳解,我們繼續解析獲取 bean 實例裏的核心內容:創建 bean 實例。
正文
首先,我們進入 createBean 方法。
createBean
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 1.解析beanName對應的Bean的類型,例如:com.joonwhee.open.demo.service.impl.UserServiceImpl
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
// 如果resolvedClass存在,並且mdb的beanClass類型不是Class,並且mdb的beanClass不爲空(則代表beanClass存的是Class的name),
// 則使用mdb深拷貝一個新的RootBeanDefinition副本,並且將解析的Class賦值給拷貝的RootBeanDefinition副本的beanClass屬性,
// 該拷貝副本取代mdb用於後續的操作
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 2.驗證及準備覆蓋的方法(對override屬性進行標記及驗證)
mbdToUse.prepareMethodOverrides();
} catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 3.實例化前的處理,給InstantiationAwareBeanPostProcessor一個機會返回代理對象來替代真正的bean實例,達到“短路”效果
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 4.如果bean不爲空,則會跳過Spring默認的實例化過程,直接使用返回的bean
if (bean != null) {
return bean;
}
} catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
// 5.創建Bean實例(真正創建Bean的方法)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
// 6.返回創建的Bean實例
return beanInstance;
}
3.實例化前的處理,給 InstantiationAwareBeanPostProcessor 一個機會返回代理對象來替代真正的 bean 實例,從而跳過 Spring 默認的實例化過程,達到“短路”效果,見代碼塊1詳解。
5.創建 bean 實例,見代碼塊3詳解。
代碼塊1:resolveBeforeInstantiation
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
// 1.mbd不是合成的,並且BeanFactory中存在InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 2.解析beanName對應的Bean實例的類型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 3.實例化前的後置處理器應用(處理InstantiationAwareBeanPostProcessor)
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
// 4.如果返回的bean不爲空,會跳過Spring默認的實例化過程,
// 所以只能在這裏調用BeanPostProcessor實現類的postProcessAfterInitialization方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// 5.如果bean不爲空,則將beforeInstantiationResolved賦值爲true,代表在實例化之前已經解析
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
3.實例化前的後置處理器應用,見代碼塊2詳解。
4.實例化後的後置處理器應用,見 Spring IoC:getBean詳解 中的代碼塊4。
代碼塊2:applyBeanPostProcessorsBeforeInstantiation
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
// 1.遍歷當前BeanFactory中的BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 2.應用InstantiationAwareBeanPostProcessor後置處理器,允許postProcessBeforeInstantiation方法返回bean對象的代理
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 3.執行postProcessBeforeInstantiation方法,在Bean實例化前操作,
// 該方法可以返回一個構造完成的Bean實例,從而不會繼續執行創建Bean實例的“正規的流程”,達到“短路”的效果。
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
// 4.如果result不爲空,也就是有後置處理器返回了bean實例對象,則會跳過Spring默認的實例化過程
return result;
}
}
}
return null;
}
在實例化之前執行 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法,該方法可以返回 bean 實例的代理,從而跳過 Spring 默認的實例化過程。
代碼塊3:doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// 1.新建Bean包裝類
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 2.如果是FactoryBean,則需要先移除未完成的FactoryBean實例的緩存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 3.根據beanName、mbd、args,使用對應的策略創建Bean實例,並返回包裝類BeanWrapper
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 4.拿到創建好的Bean實例
final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
// 5.拿到Bean實例的類型
Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
mbd.resolvedTargetType = beanType;
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 6.應用後置處理器MergedBeanDefinitionPostProcessor,允許修改MergedBeanDefinition,
// Autowired註解正是通過此方法實現注入類型的預解析
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 7.判斷是否需要提早曝光實例:單例 && 允許循環依賴 && 當前bean正在創建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 8.提前曝光beanName的ObjectFactory,用於解決循環引用
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
// 8.1 應用後置處理器SmartInstantiationAwareBeanPostProcessor,允許返回指定bean的早期引用,若沒有則直接返回bean
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// Initialize the bean instance. 初始化bean實例。
Object exposedObject = bean;
try {
// 9.對bean進行屬性填充;其中,可能存在依賴於其他bean的屬性,則會遞歸初始化依賴的bean實例
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 10.對bean進行初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
// 11.如果允許提前曝光實例,則進行循環依賴檢查
Object earlySingletonReference = getSingleton(beanName, false);
// 11.1 earlySingletonReference只有在當前解析的bean存在循環依賴的情況下才會不爲空
if (earlySingletonReference != null) {
if (exposedObject == bean) {
// 11.2 如果exposedObject沒有在initializeBean方法中被增強,則不影響之前的循環引用
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 11.3 如果exposedObject在initializeBean方法中被增強 && 不允許在循環引用的情況下使用注入原始bean實例
// && 當前bean有被其他bean依賴
// 11.4 拿到依賴當前bean的所有bean的beanName數組
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 11.5 嘗試移除這些bean的實例,因爲這些bean依賴的bean已經被增強了,他們依賴的bean相當於髒數據
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
// 11.6 移除失敗的添加到 actualDependentBeans
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
// 11.7 如果存在移除失敗的,則拋出異常,因爲存在bean依賴了“髒數據”
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.");
}
}
}
}
// Register bean as disposable.
try {
// 12.註冊用於銷燬的bean,執行銷燬操作的有三種:自定義destroy方法、DisposableBean接口、DestructionAwareBeanPostProcessor
registerDisposableBeanIfNecessary(beanName, bean, mbd);
} catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 13.完成創建並返回
return exposedObject;
}
真正創建 bean 實例的方法,整個系列文章中的核心中的核心,很多代碼是前後相關聯的,需要反覆閱讀才能很好的理解。
3.根據 beanName、mbd、args,使用對應的策略創建 bean 實例,並返回包裝類 BeanWrapper,見代碼塊4詳解。
由於創建 bean 實例的過程過長,限於篇幅關係,本文只介紹第 3 點的 createBeanInstance 方法,剩餘的內容將在下一篇文章介紹。
代碼塊4:createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析bean的類型信息
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
// beanClass不爲空 && beanClass不是公開類(不是public修飾) && 該bean不允許訪問非公共構造函數和方法,則拋異常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// 1.如果存在工廠方法則使用工廠方法實例化bean對象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// resolved: 構造函數或工廠方法是否已經解析過
boolean resolved = false;
// autowireNecessary: 是否需要自動注入(即是否需要解析構造函數參數)
boolean autowireNecessary = false;
if (args == null) {
// 2.加鎖
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
// 2.1 如果resolvedConstructorOrFactoryMethod緩存不爲空,則將resolved標記爲已解析
resolved = true;
// 2.2 根據constructorArgumentsResolved判斷是否需要自動注入
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 3.如果已經解析過,則使用resolvedConstructorOrFactoryMethod緩存裏解析好的構造函數方法
if (autowireNecessary) {
// 3.1 需要自動注入,則執行構造函數自動注入
return autowireConstructor(beanName, mbd, null, null);
} else {
// 3.2 否則使用默認的構造函數進行bean的實例化
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
// 4.應用後置處理器SmartInstantiationAwareBeanPostProcessor,拿到bean的候選構造函數
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 5.如果ctors不爲空 || mbd的注入方式爲AUTOWIRE_CONSTRUCTOR || mdb定義了構造函數的參數值 || args不爲空,則執行構造函數自動注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 6.沒有特殊處理,則使用默認的構造函數進行bean的實例化
return instantiateBean(beanName, mbd);
}
創建實例的方法通常有以下幾種:工廠方法、構造函數自動裝配(通常指帶有參數的構造函數)、簡單實例化(默認的構造函數)。其中工廠方法現在基本不使用了,不再解析;簡單實例化過程比較簡單,也不解析;本文只對構造函數自動裝配進行解析,該方法對應代碼中的:3.1 和 5。
4.應用後置處理器 SmartInstantiationAwareBeanPostProcessor,拿到給定 bean 的候選構造函數,見代碼塊4.5詳解。
5.執行構造函數自動注入,見代碼塊5詳解。
代碼塊4.5:determineConstructorsFromBeanPostProcessors
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(Class<?> beanClass, String beanName)
throws BeansException {
if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
// 1.遍歷所有的BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 2.調用SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors方法,
// 該方法可以返回要用於beanClass的候選構造函數
// 例如:使用@Autowire註解修飾構造函數,則該構造函數在這邊會被AutowiredAnnotationBeanPostProcessor找到
Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
if (ctors != null) {
// 3.如果ctors不爲空,則不再繼續執行其他的SmartInstantiationAwareBeanPostProcessor
return ctors;
}
}
}
}
return null;
}
2.調用 SmartInstantiationAwareBeanPostProcessor 的 determineCandidateConstructors 方法,該方法可以返回要用於 beanClass 的候選構造函數。使用 @Autowire 註解修飾構造函數,則該構造函數在這邊會被 AutowiredAnnotationBeanPostProcessor 找到,該內容會在之後介紹 @Autowire 的文章中單獨介紹。
代碼塊5:autowireConstructor
protected BeanWrapper autowireConstructor(
String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {
return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
}
public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
Constructor<?>[] chosenCtors, final Object[] explicitArgs) {
// 定義bean包裝類
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// 最終用於實例化的構造函數
Constructor<?> constructorToUse = null;
// 最終用於實例化的參數Holder
ArgumentsHolder argsHolderToUse = null;
// 最終用於實例化的構造函數參數
Object[] argsToUse = null;
// 1.解析出要用於實例化的構造函數參數
if (explicitArgs != null) {
// 1.1 如果explicitArgs不爲空,則構造函數的參數直接使用explicitArgs
// 通過getBean方法調用時,顯示指定了參數,則explicitArgs就不爲null
argsToUse = explicitArgs;
}
else {
// 1.2 嘗試從緩存中獲取已經解析過的構造函數參數
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
// 1.2.1 拿到緩存中已解析的構造函數或工廠方法
constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
// 1.2.2 如果constructorToUse不爲空 && mbd標記了構造函數參數已解析
if (constructorToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached constructor...
// 1.2.3 從緩存中獲取已解析的構造函數參數
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
// 1.2.4 如果resolvedConstructorArguments爲空,則從緩存中獲取準備用於解析的構造函數參數,
// constructorArgumentsResolved爲true時,resolvedConstructorArguments和
// preparedConstructorArguments必然有一個緩存了構造函數的參數
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
// 1.2.5 如果argsToResolve不爲空,則對構造函數參數進行解析,
// 如給定方法的構造函數 A(int,int)則通過此方法後就會把配置中的("1","1")轉換爲(1,1)
argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
}
}
// 2.如果構造函數沒有被緩存,則通過配置文件獲取
if (constructorToUse == null) {
// Need to resolve the constructor.
// 2.1 檢查是否需要自動裝配:chosenCtors不爲空 || autowireMode爲AUTOWIRE_CONSTRUCTOR
// 例子:當chosenCtors不爲空時,代表有構造函數通過@Autowire修飾,因此需要自動裝配
boolean autowiring = (chosenCtors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
ConstructorArgumentValues resolvedValues = null;
// 構造函數參數個數
int minNrOfArgs;
if (explicitArgs != null) {
// 2.2 explicitArgs不爲空,則使用explicitArgs的length作爲minNrOfArgs的值
minNrOfArgs = explicitArgs.length;
}
else {
// 2.3 獲得mbd的構造函數的參數值(indexedArgumentValues:帶index的參數值;genericArgumentValues:通用的參數值)
ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
// 2.4 創建ConstructorArgumentValues對象resolvedValues,用於承載解析後的構造函數參數的值
resolvedValues = new ConstructorArgumentValues();
// 2.5 解析mbd的構造函數的參數,並返回參數個數
minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
// 注:這邊解析mbd中的構造函數參數值,主要是處理我們通過xml方式定義的構造函數注入的參數,
// 但是如果我們是通過@Autowire註解直接修飾構造函數,則mbd是沒有這些參數值的
}
// 3.確認構造函數的候選者
// Take specified constructors, if any.
// 3.1 如果入參chosenCtors不爲空,則將chosenCtors的構造函數作爲候選者
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
Class<?> beanClass = mbd.getBeanClass();
try {
// 3.2 如果入參chosenCtors爲空,則獲取beanClass的構造函數
// (mbd是否允許訪問非公共構造函數和方法 ? 所有聲明的構造函數:公共構造函數)
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Resolution of declared constructors on bean Class [" + beanClass.getName() +
"] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
}
}
// 3.3 對給定的構造函數排序:先按方法修飾符排序:public排非public前面,再按構造函數參數個數排序:參數多的排前面
AutowireUtils.sortConstructors(candidates);
// 最小匹配權重,權重越小,越接近我們要找的目標構造函數
int minTypeDiffWeight = Integer.MAX_VALUE;
Set<Constructor<?>> ambiguousConstructors = null;
LinkedList<UnsatisfiedDependencyException> causes = null;
// 4.遍歷所有構造函數候選者,找出符合條件的構造函數
for (Constructor<?> candidate : candidates) {
// 4.1 拿到當前遍歷的構造函數的參數類型數組
Class<?>[] paramTypes = candidate.getParameterTypes();
if (constructorToUse != null && argsToUse.length > paramTypes.length) {
// Already found greedy constructor that can be satisfied ->
// do not look any further, there are only less greedy constructors left.
// 4.2 如果已經找到滿足的構造函數 && 目標構造函數需要的參數個數大於當前遍歷的構造函數的參數個數則終止,
// 因爲遍歷的構造函數已經排過序,後面不會有更合適的候選者了
break;
}
if (paramTypes.length < minNrOfArgs) {
// 4.3 如果當前遍歷到的構造函數的參數個數小於我們所需的參數個數,則直接跳過該構造函數
continue;
}
ArgumentsHolder argsHolder;
if (resolvedValues != null) {
// 存在參數則根據參數值來匹配參數類型
try {
// 4.4 resolvedValues不爲空,
// 4.4.1 獲取當前遍歷的構造函數的參數名稱
// 4.4.1.1 解析使用ConstructorProperties註解的構造函數參數
String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
if (paramNames == null) {
// 4.4.1.2 獲取參數名稱解析器
ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
if (pnd != null) {
// 4.4.1.3 使用參數名稱解析器獲取當前遍歷的構造函數的參數名稱
paramNames = pnd.getParameterNames(candidate);
}
}
// 4.4.2 創建一個參數數組以調用構造函數或工廠方法,
// 主要是通過參數類型和參數名解析構造函數或工廠方法所需的參數(如果參數是其他bean,則會解析依賴的bean)
argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
getUserDeclaredConstructor(candidate), autowiring);
}
catch (UnsatisfiedDependencyException ex) {
// 4.4.3 參數匹配失敗,則拋出異常
if (this.beanFactory.logger.isTraceEnabled()) {
this.beanFactory.logger.trace(
"Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
}
// Swallow and try next constructor.
if (causes == null) {
causes = new LinkedList<UnsatisfiedDependencyException>();
}
causes.add(ex);
continue;
}
}
else {
// 4.5 resolvedValues爲空,則explicitArgs不爲空,即給出了顯式參數
// Explicit arguments given -> arguments length must match exactly.
// 4.5.1 如果當前遍歷的構造函數參數個數與explicitArgs長度不相同,則跳過該構造函數
if (paramTypes.length != explicitArgs.length) {
continue;
}
// 4.5.2 使用顯式給出的參數構造ArgumentsHolder
argsHolder = new ArgumentsHolder(explicitArgs);
}
// 4.6 根據mbd的解析構造函數模式(true: 寬鬆模式(默認),false:嚴格模式),
// 將argsHolder的參數和paramTypes進行比較,計算paramTypes的類型差異權重值
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 4.7 類型差異權重值越小,則說明構造函數越匹配,則選擇此構造函數
if (typeDiffWeight < minTypeDiffWeight) {
// 將要使用的參數都替換成差異權重值更小的
constructorToUse = candidate;
argsHolderToUse = argsHolder;
argsToUse = argsHolder.arguments;
minTypeDiffWeight = typeDiffWeight;
// 如果出現權重值更小的候選者,則將ambiguousConstructors清空,允許之前存在權重值相同的候選者
ambiguousConstructors = null;
}
// 4.8 如果存在兩個候選者的權重值相同,並且是當前遍歷過權重值最小的
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
// 將這兩個候選者都添加到ambiguousConstructors
if (ambiguousConstructors == null) {
ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
ambiguousConstructors.add(constructorToUse);
}
ambiguousConstructors.add(candidate);
}
}
if (constructorToUse == null) {
// 5.如果最終沒有找到匹配的構造函數,則進行異常處理
if (causes != null) {
UnsatisfiedDependencyException ex = causes.removeLast();
for (Exception cause : causes) {
this.beanFactory.onSuppressedException(cause);
}
throw ex;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Could not resolve matching constructor " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
}
else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
// 6.如果找到了匹配的構造函數,但是存在多個(ambiguousConstructors不爲空) && 解析構造函數的模式爲嚴格模式,則拋出異常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Ambiguous constructor matches found in bean '" + beanName + "' " +
"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
ambiguousConstructors);
}
if (explicitArgs == null) {
// 7.將解析的構造函數和參數放到緩存
argsHolderToUse.storeCache(mbd, constructorToUse);
}
}
try {
Object beanInstance;
// 8.根據實例化策略以及得到的構造函數及構造函數參數實例化bean
if (System.getSecurityManager() != null) {
final Constructor<?> ctorToUse = constructorToUse;
final Object[] argumentsToUse = argsToUse;
beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
return beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
}
}, beanFactory.getAccessControlContext());
}
else {
beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}
// 9.將構造的實例加入BeanWrapper中,並返回
bw.setBeanInstance(beanInstance);
return bw;
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean instantiation via constructor failed", ex);
}
}
例子:
這邊 2.3 - 2.5 解析的 mbd 的構造函數參數值主要是針對通過 XML 注入的方式,例如以下例子:
sping 配置文件:
<bean class="com.joonwhee.open.demo.service.impl.DemoServiceImpl">
<constructor-arg index="2" name="name" value="joonwhee"/>
<constructor-arg name="age" value="25"/>
<constructor-arg name="skillList">
<list>
<value>sing</value>
<value>basketball</value>
</list>
</constructor-arg>
<constructor-arg index="0" name="id" value="1"/>
<constructor-arg name="userService" ref="userService"/>
</bean>
<bean id="userService" class="com.joonwhee.open.demo.service.impl.UserServiceImpl"/>
構造函數參數中帶 index 的會被解析到 ConstructorArgumentValues.indexedArgumentValues,不帶的會被解析到 ConstructorArgumentValues.genericArgumentValues。
DemoServiceImpl.java
@Service
public class DemoServiceImpl implements DemoService {
private Integer id;
private Integer age;
private String name;
private List<String> skillList;
private UserService userService;
public DemoServiceImpl(Integer id, Integer age, String name, List<String> skillList, UserService userService) {
this.id = id;
this.age = age;
this.name = name;
this.skillList = skillList;
this.userService = userService;
}
@Override
public void sayHello() {
}
}
2.5 解析 mbd 的構造函數的參數,並返回參數個數,見代碼塊6詳解。
4.4.2 創建一個參數數組以調用構造函數或工廠方法,主要是通過參數類型和參數名解析構造函數或工廠方法所需的參數(如果參數是其他 bean,則會解析依賴的 bean),見代碼塊7詳解。
7.將解析的構造函數和參數放到緩存,見代碼塊19詳解。
代碼塊6:resolveConstructorArguments
private int resolveConstructorArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
ConstructorArgumentValues cargs, ConstructorArgumentValues resolvedValues) {
// 1.構建bean定義值解析器
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
TypeConverter converter = (customConverter != null ? customConverter : bw);
BeanDefinitionValueResolver valueResolver =
new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
// 2.minNrOfArgs初始化爲indexedArgumentValues和genericArgumentValues的的參數個數總和
int minNrOfArgs = cargs.getArgumentCount();
// 3.遍歷解析帶index的參數值
for (Map.Entry<Integer, ConstructorArgumentValues.ValueHolder> entry : cargs.getIndexedArgumentValues().entrySet()) {
int index = entry.getKey();
if (index < 0) {
// index從0開始,不允許小於0
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Invalid constructor argument index: " + index);
}
// 3.1 如果index大於minNrOfArgs,則修改minNrOfArgs
if (index > minNrOfArgs) {
// index是從0開始,並且是有序遞增的,所以當有參數的index=5時,代表該方法至少有6個參數
minNrOfArgs = index + 1;
}
ConstructorArgumentValues.ValueHolder valueHolder = entry.getValue();
// 3.2 解析參數值
if (valueHolder.isConverted()) {
// 3.2.1 如果參數值已經轉換過,則直接將index和valueHolder添加到resolvedValues的indexedArgumentValues屬性
resolvedValues.addIndexedArgumentValue(index, valueHolder);
} else {
// 3.2.2 如果值還未轉換過,則先進行轉換
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
// 3.2.3 使用轉換後的resolvedValue構建新的ValueHolder
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
// 3.2.4 將轉換前的valueHolder保存到新的ValueHolder的source屬性
resolvedValueHolder.setSource(valueHolder);
// 3.2.5 將index和新的ValueHolder添加到resolvedValues的indexedArgumentValues屬性
resolvedValues.addIndexedArgumentValue(index, resolvedValueHolder);
}
}
// 4.遍歷解析通用參數值(不帶index)
for (ConstructorArgumentValues.ValueHolder valueHolder : cargs.getGenericArgumentValues()) {
if (valueHolder.isConverted()) {
// 4.1 如果參數值已經轉換過,則直接將valueHolder添加到resolvedValues的genericArgumentValues屬性
resolvedValues.addGenericArgumentValue(valueHolder);
} else {
// 4.2 如果值還未轉換過,則先進行轉換
Object resolvedValue =
valueResolver.resolveValueIfNecessary("constructor argument", valueHolder.getValue());
// 4.3 使用轉換後的resolvedValue構建新的ValueHolder
ConstructorArgumentValues.ValueHolder resolvedValueHolder =
new ConstructorArgumentValues.ValueHolder(resolvedValue, valueHolder.getType(), valueHolder.getName());
// 4.4 將轉換前的valueHolder保存到新的ValueHolder的source屬性
resolvedValueHolder.setSource(valueHolder);
// 4.5 將新的ValueHolder添加到resolvedValues的genericArgumentValues屬性
resolvedValues.addGenericArgumentValue(resolvedValueHolder);
}
}
// 5.返回構造函數參數的個數
return minNrOfArgs;
}
代碼塊7:createArgumentArray
private ArgumentsHolder createArgumentArray(
String beanName, RootBeanDefinition mbd, ConstructorArgumentValues resolvedValues,
BeanWrapper bw, Class<?>[] paramTypes, String[] paramNames, Object methodOrCtor,
boolean autowiring) throws UnsatisfiedDependencyException {
TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
// 獲取類型轉換器
TypeConverter converter = (customConverter != null ? customConverter : bw);
// 新建一個ArgumentsHolder來存放匹配到的參數
ArgumentsHolder args = new ArgumentsHolder(paramTypes.length);
Set<ConstructorArgumentValues.ValueHolder> usedValueHolders =
new HashSet<ConstructorArgumentValues.ValueHolder>(paramTypes.length);
Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
// 1.遍歷參數類型數組
for (int paramIndex = 0; paramIndex < paramTypes.length; paramIndex++) {
// 拿到當前遍歷的參數類型
Class<?> paramType = paramTypes[paramIndex];
// 拿到當前遍歷的參數名
String paramName = (paramNames != null ? paramNames[paramIndex] : "");
// Try to find matching constructor argument value, either indexed or generic.
// 2.查找當前遍歷的參數,是否在mdb對應的bean的構造函數參數中存在index、類型和名稱匹配的
ConstructorArgumentValues.ValueHolder valueHolder =
resolvedValues.getArgumentValue(paramIndex, paramType, paramName, usedValueHolders);
// If we couldn't find a direct match and are not supposed to autowire,
// let's try the next generic, untyped argument value as fallback:
// it could match after type conversion (for example, String -> int).
// 3.如果我們找不到直接匹配並且不應該自動裝配,那麼讓我們嘗試下一個通用的無類型參數值作爲降級方法:它可以在類型轉換後匹配(例如,String - > int)。
if (valueHolder == null && (!autowiring || paramTypes.length == resolvedValues.getArgumentCount())) {
valueHolder = resolvedValues.getGenericArgumentValue(null, null, usedValueHolders);
}
if (valueHolder != null) {
// 4.valueHolder不爲空,存在匹配的參數
// We found a potential match - let's give it a try.
// Do not consider the same value definition multiple times!
// 將valueHolder添加到usedValueHolders
usedValueHolders.add(valueHolder);
// 原始屬性值
Object originalValue = valueHolder.getValue();
// 轉換後的屬性值
Object convertedValue;
if (valueHolder.isConverted()) {
// 4.1 如果valueHolder已經轉換過
// 4.1.1 則直接獲取轉換後的值
convertedValue = valueHolder.getConvertedValue();
// 4.1.2 將convertedValue作爲args在paramIndex位置的預備參數
args.preparedArguments[paramIndex] = convertedValue;
} else {
// 4.2 如果valueHolder還未轉換過
// 4.2.1 拿到原始的ValueHolder
ConstructorArgumentValues.ValueHolder sourceHolder =
(ConstructorArgumentValues.ValueHolder) valueHolder.getSource();
// 4.2.2 拿到原始參數值
Object sourceValue = sourceHolder.getValue();
// 4.2.3 將方法(此處爲構造函數)和參數索引封裝成MethodParameter(MethodParameter是封裝方法和參數索引的工具類)
MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);
try {
// 4.2.4 將原始值轉換爲paramType類型的值(如果類型無法轉,拋出TypeMismatchException)
convertedValue = converter.convertIfNecessary(originalValue, paramType, methodParam);
// TODO re-enable once race condition has been found (SPR-7423)
/*
if (originalValue == sourceValue || sourceValue instanceof TypedStringValue) {
// Either a converted value or still the original one: store converted value.
sourceHolder.setConvertedValue(convertedValue);
args.preparedArguments[paramIndex] = convertedValue;
}
else {
*/
// 4.2.5 args標記爲需要解析
args.resolveNecessary = true;
// 4.2.6 將convertedValue作爲args在paramIndex位置的預備參數
args.preparedArguments[paramIndex] = sourceValue;
// }
} catch (TypeMismatchException ex) {
// 4.2.7 如果類型轉換失敗,則拋出異常
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Could not convert argument value of type [" +
ObjectUtils.nullSafeClassName(valueHolder.getValue()) +
"] to required type [" + paramType.getName() + "]: " + ex.getMessage());
}
}
// 4.3 將convertedValue作爲args在paramIndex位置的參數
args.arguments[paramIndex] = convertedValue;
// 4.4 將originalValue作爲args在paramIndex位置的原始參數
args.rawArguments[paramIndex] = originalValue;
} else {
// 5.valueHolder爲空,不存在匹配的參數
// 5.1 將方法(此處爲構造函數)和參數索引封裝成MethodParameter
MethodParameter methodParam = MethodParameter.forMethodOrConstructor(methodOrCtor, paramIndex);
// No explicit match found: we're either supposed to autowire or
// have to fail creating an argument array for the given constructor.
// 5.2 找不到明確的匹配,並且不是自動裝配,則拋出異常
if (!autowiring) {
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
"Ambiguous argument values for parameter of type [" + paramType.getName() +
"] - did you specify the correct bean references as arguments?");
}
try {
// 5.3 如果是自動裝配,則調用用於解析自動裝配參數的方法,返回的結果爲依賴的bean實例對象
// 例如:@Autowire修飾構造函數,自動注入構造函數中的參數bean就是在這邊處理
Object autowiredArgument =
resolveAutowiredArgument(methodParam, beanName, autowiredBeanNames, converter);
// 5.4 將通過自動裝配解析出來的參數賦值給args
args.rawArguments[paramIndex] = autowiredArgument;
args.arguments[paramIndex] = autowiredArgument;
args.preparedArguments[paramIndex] = new AutowiredArgumentMarker();
args.resolveNecessary = true;
} catch (BeansException ex) {
// 5.5 如果自動裝配解析失敗,則會拋出異常
throw new UnsatisfiedDependencyException(
mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam), ex);
}
}
}
// 6.如果依賴了其他的bean,則註冊依賴關係
for (String autowiredBeanName : autowiredBeanNames) {
this.beanFactory.registerDependentBean(autowiredBeanName, beanName);
if (this.beanFactory.logger.isDebugEnabled()) {
this.beanFactory.logger.debug("Autowiring by type from bean name '" + beanName +
"' via " + (methodOrCtor instanceof Constructor ? "constructor" : "factory method") +
" to bean named '" + autowiredBeanName + "'");
}
}
return args;
}
5.3 如果是自動裝配,則調用用於解析自動裝配參數的方法,返回的結果爲依賴的 bean 實例對象,見代碼塊8詳解。
代碼塊8:resolveAutowiredArgument
protected Object resolveAutowiredArgument(
MethodParameter param, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) {
// 1.如果參數類型爲InjectionPoint
if (InjectionPoint.class.isAssignableFrom(param.getParameterType())) {
// 1.1 拿到當前的InjectionPoint(存儲了當前正在解析依賴的方法參數信息,DependencyDescriptor)
InjectionPoint injectionPoint = currentInjectionPoint.get();
if (injectionPoint == null) {
// 1.2 當前injectionPoint爲空,則拋出異常:目前沒有可用的InjectionPoint
throw new IllegalStateException("No current InjectionPoint available for " + param);
}
// 1.3 返回當前的InjectionPoint
return injectionPoint;
}
// 2.解析指定依賴,DependencyDescriptor:將MethodParameter的方法參數索引信息封裝成DependencyDescriptor
return this.beanFactory.resolveDependency(
new DependencyDescriptor(param, true), beanName, autowiredBeanNames, typeConverter);
}
2.解析指定依賴,這邊的 DependencyDescriptor 主要是封裝了依賴的方法和參數的信息,見代碼塊9詳解。
代碼塊9:resolveDependency
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
if (javaUtilOptionalClass == descriptor.getDependencyType()) {
// 1.javaUtilOptionalClass類注入的特殊處理
return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
} else if (ObjectFactory.class == descriptor.getDependencyType() ||
// 2.ObjectFactory類注入的特殊處理
ObjectProvider.class == descriptor.getDependencyType()) {
return new DependencyObjectProvider(descriptor, requestingBeanName);
} else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
// 3.javaxInjectProviderClass類注入的特殊處理
return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
} else {
// 4.通用類注入的處理
// 4.1 如有必要,請獲取延遲解析代理
Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
descriptor, requestingBeanName);
if (result == null) {
// 4.2 解析依賴關係,返回的result爲創建好的依賴對象的bean實例
result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
}
return result;
}
}
4.2 解析依賴關係,返回的 result 爲創建好的依賴對象的 bean 實例,見代碼塊10詳解。
代碼塊10:doResolveDependency
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {
// 1.設置當前的descriptor(存儲了方法參數等信息)爲當前注入點
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
// 2.如果是ShortcutDependencyDescriptor,則直接通過getBean方法獲取Bean實例,並返回;否則返回null
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 3.拿到descriptor包裝的方法的參數類型(通過參數索引定位到具體的參數)
Class<?> type = descriptor.getDependencyType();
// 4.用於支持spring中新增的註解@Value(確定給定的依賴項是否聲明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());
// 4.1 如果使用了@Value註解,則將解析到的值轉換成所需的類型並返回
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
// 5.解析MultipleBean(下文的MultipleBean都是指類型爲:Array、Collection、Map)
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
// 5.1 如果確實是容器類型的屬性,則直接返回解析結果
return multipleBeans;
}
// 6.查找與所需類型匹配的Bean實例(matchingBeans,key:beanName;value:匹配的bean實例,或者匹配的bean實例的類型)
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 6.1 如果require屬性爲true,而找到的匹配Bean卻爲空則拋出異常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
// 6.2 如果require屬性爲false,而找到的匹配Bean卻爲空,則返回nul
return null;
}
String autowiredBeanName;
Object instanceCandidate;
if (matchingBeans.size() > 1) {
// 7.非MultipleBean,但是有多個候選者
// 7.1 從多個候選者中選出最優的那個
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(type, matchingBeans);
} else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
// 7.2.拿到autowiredBeanName對應的value(bean實例或bean實例類型)
instanceCandidate = matchingBeans.get(autowiredBeanName);
} else {
// 8.只找到了一個候選者,則直接使用該候選者
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
// 9.將依賴的beanName加到autowiredBeanNames中
autowiredBeanNames.add(autowiredBeanName);
}
// 10.如果instanceCandidate爲Class,則instanceCandidate爲bean實例的類型,執行descriptor.resolveCandidate方法,
// 通過getBean方法獲取bean實例並返回;如果instanceCandidate不是Class,則instanceCandidate爲bean實例,直接返回該實例
return (instanceCandidate instanceof Class ?
descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
} finally {
// 11.執行結束,將注入點修改成原來的注入點
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}
2.如果是 ShortcutDependencyDescriptor,則直接通過 getBean 方法獲取 bean 實例,並返回;否則返回 null。
通過構造函數注入依賴的 bean 實例的整個過程是不會出現涉及到 ShortcutDependencyDescriptor 的。ShortcutDependencyDescriptor 主要用於 @Autowire 註解,在解析 @Autowire 註解的時候,當第一次注入依賴的 bean 實例後,會將該依賴的 bean 的信息封裝成 ShortcutDependencyDescriptor ,放到緩存中去,下一次需要依賴注入該 bean 時,可以直接快速的拿到該 bean 實例。
6.查找與所需類型匹配的 bean 實例,這邊的返回結果 matchingBeans 的 key 是 beanName,而 value 有兩種情況:一種是匹配的 bean 實例,另一種是匹配的 bean 實例的類型,見代碼塊11詳解。
7.1 從多個候選者中選出最優的那個,見代碼塊16詳解。
代碼塊11:findAutowireCandidates
protected Map<String, Object> findAutowireCandidates(
String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
// 1.獲取給定類型的所有beanName,包括在祖先工廠中定義的beanName
String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this, requiredType, true, descriptor.isEager());
Map<String, Object> result = new LinkedHashMap<String, Object>(candidateNames.length);
// 2.首先從已經解析的依賴關係緩存中尋找是否存在我們想要的類型
for (Class<?> autowiringType : this.resolvableDependencies.keySet()) {
// 2.1 autowiringType是否與requiredType相同,或者是requiredType的超類、超接口
if (autowiringType.isAssignableFrom(requiredType)) {
// 2.2 如果requiredType匹配,則從緩存中拿到相應的自動裝配值(bean實例)
Object autowiringValue = this.resolvableDependencies.get(autowiringType);
// 2.3 根據給定的所需類型解析給定的自動裝配值
autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
if (requiredType.isInstance(autowiringValue)) {
// 2.4 將autowiringValue放到結果集中,此時的value爲bean實例
result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
break;
}
}
}
// 3.遍歷從容器中獲取到的類型符合的beanName
for (String candidate : candidateNames) {
// isAutowireCandidate:判斷是否有資格作爲依賴注入的候選者
// 3.1 如果不是自引用 && candidate有資格作爲依賴注入的候選者
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
// 3.2 將候選者添加到result中
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
// 4.如果結果爲空 && type不是MultipleBean(Array、Collection、Map),則使用降級匹配
if (result.isEmpty() && !indicatesMultipleBeans(requiredType)) {
// Consider fallback matches if the first pass failed to find anything...
// 4.1 使用降級匹配(跟正常匹配類似)
DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
for (String candidate : candidateNames) {
if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor)) {
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
if (result.isEmpty()) {
// Consider self references as a final pass...
// but in the case of a dependency collection, not the very same bean itself.
// 5.如果使用降級匹配結果還是空,則考慮自引用
for (String candidate : candidateNames) {
if (isSelfReference(beanName, candidate) &&
(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
isAutowireCandidate(candidate, fallbackDescriptor)) {
// 5.1 如果是自引用 && (descriptor不是MultiElementDescriptor || beanName不等於候選者)
// && candidate允許依賴注入,則將候選者添加到result中
addCandidateEntry(result, candidate, descriptor, requiredType);
}
}
}
}
// 6.返回符合條件的候選者
return result;
}
3.1 isAutowireCandidate:判斷是否有資格作爲依賴注入的候選者,見代碼塊12詳解。
3.2 將候選者添加到 result 中,見代碼塊15詳解。
代碼塊12:isAutowireCandidate
@Override
public boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
throws NoSuchBeanDefinitionException {
// getAutowireCandidateResolver: 返回BeanFactory的@Autowire解析器,開啓註解後的解析器爲:ContextAnnotationAutowireCandidateResolver
// 解析beanName對應的bean是否有資格作爲候選者
return isAutowireCandidate(beanName, descriptor, getAutowireCandidateResolver());
}
protected boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor, AutowireCandidateResolver resolver)
throws NoSuchBeanDefinitionException {
// 1.解析beanName,去掉FactoryBean的修飾符“&”
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
if (containsBeanDefinition(beanDefinitionName)) {
// 2.beanDefinitionMap緩存中存在beanDefinitionName:通過beanDefinitionName緩存拿到MergedBeanDefinition,
// 將MergedBeanDefinition作爲參數,解析beanName是否有資格作爲候選者
return isAutowireCandidate(beanName, getMergedLocalBeanDefinition(beanDefinitionName), descriptor, resolver);
} else if (containsSingleton(beanName)) {
// 3.singletonObjects緩存中存在beanName:使用beanName構建RootBeanDefinition作爲參數,解析beanName是否有資格作爲候選者
return isAutowireCandidate(beanName, new RootBeanDefinition(getType(beanName)), descriptor, resolver);
}
// 4.在beanDefinitionMap緩存和singletonObjects緩存中都不存在,則在parentBeanFactory中遞歸解析beanName是否有資格作爲候選者
BeanFactory parent = getParentBeanFactory();
if (parent instanceof DefaultListableBeanFactory) {
// No bean definition found in this factory -> delegate to parent.
return ((DefaultListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor, resolver);
} else if (parent instanceof ConfigurableListableBeanFactory) {
// If no DefaultListableBeanFactory, can't pass the resolver along.
return ((ConfigurableListableBeanFactory) parent).isAutowireCandidate(beanName, descriptor);
} else {
return true;
}
}
這邊的 ContextAnnotationAutowireCandidateResolver 在 Spring IoC:context:component-scan節點詳解 文中的代碼塊17被賦值給 BeanFacoty 的 autowireCandidateResolver 屬性。
2.繼續解析 beanName 是否有資格作爲候選者,見代碼塊13詳解。
代碼塊13:isAutowireCandidate
protected boolean isAutowireCandidate(String beanName, RootBeanDefinition mbd,
DependencyDescriptor descriptor, AutowireCandidateResolver resolver) {
// 1.解析beanName,去掉FactoryBean的修飾符“&”
String beanDefinitionName = BeanFactoryUtils.transformedBeanName(beanName);
// 2.解析mbd的beanClass
resolveBeanClass(mbd, beanDefinitionName);
if (mbd.isFactoryMethodUnique) {
boolean resolve;
synchronized (mbd.constructorArgumentLock) {
resolve = (mbd.resolvedConstructorOrFactoryMethod == null);
}
if (resolve) {
// 3.如果緩存中已經存在解析的構造函數或工廠方法,則解析mbd中的工廠方法,並替換掉緩存中的方法
new ConstructorResolver(this).resolveFactoryMethodIfPossible(mbd);
}
}
// 4.使用resolver解析器解析mbd是否有資格作爲依賴注入的候選者
return resolver.isAutowireCandidate(
new BeanDefinitionHolder(mbd, beanName, getAliases(beanDefinitionName)), descriptor);
}
4.使用 resolver(ContextAnnotationAutowireCandidateResolver)解析器解析 mbd 是否有資格作爲依賴注入的候選者,見代碼塊14詳解。
代碼塊14:isAutowireCandidate
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
// 1.調用父類方法判斷此bean是否可以自動注入到其他bean
boolean match = super.isAutowireCandidate(bdHolder, descriptor);
if (match && descriptor != null) {
// 2.@Qualifiers註解檢查
match = checkQualifiers(bdHolder, descriptor.getAnnotations());
if (match) {
MethodParameter methodParam = descriptor.getMethodParameter();
if (methodParam != null) {
Method method = methodParam.getMethod();
if (method == null || void.class == method.getReturnType()) {
match = checkQualifiers(bdHolder, methodParam.getMethodAnnotations());
}
}
}
}
return match;
}
// GenericTypeAwareAutowireCandidateResolver.java
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
if (!super.isAutowireCandidate(bdHolder, descriptor)) {
// If explicitly false, do not proceed with any other checks...
// 1.如果父類返回false,則直接返回false
return false;
}
// 2.descriptor爲空 || bdHolder的類型與descriptor的類型匹配,則返回true
return (descriptor == null || checkGenericTypeMatch(bdHolder, descriptor));
}
// SimpleAutowireCandidateResolver.java
@Override
public boolean isAutowireCandidate(BeanDefinitionHolder bdHolder, DependencyDescriptor descriptor) {
// 獲取此bean是否可以自動注入到其他bean(autowireCandidate屬性),默認爲true,一般不修改,因此這邊返回true
return bdHolder.getBeanDefinition().isAutowireCandidate();
}
ContextAnnotationAutowireCandidateResolver 繼承了 QualifierAnnotationAutowireCandidateResolver,所以這邊最開始會走到 QualifierAnnotationAutowireCandidateResolver 中的方法。
代碼塊15:addCandidateEntry
private void addCandidateEntry(Map<String, Object> candidates, String candidateName,
DependencyDescriptor descriptor, Class<?> requiredType) {
// 1.如果descriptor爲MultiElementDescriptor類型 || candidateName已經在singletonObjects緩存中存在
if (descriptor instanceof MultiElementDescriptor || containsSingleton(candidateName)) {
// 2.1 resolveCandidate: 通過candidateName獲取對應的bean實例
// 2.2 將beanName -> bean實例 的映射添加到candidates(此時的value爲bean實例)
candidates.put(candidateName, descriptor.resolveCandidate(candidateName, requiredType, this));
} else {
// 3.將beanName -> bean實例的類型 的映射添加到candidates(此時的value爲bean實例的類型)
candidates.put(candidateName, getType(candidateName));
}
}
當被依賴注入的屬性是 MultipleBean(Array、Collection、Map)類型,生成的依賴描述類型是 MultiElementDescriptor,因此所有的候選者均是合格的,所以會當場實例化他們(2.1)。而如果屬性的類型是非 MultipleBean,那麼可能是從多個候選者中挑一個最合適的,因此此時實例化他們就不合適了,最終會把最合適的那個實例化,如果沒有合格的則不應該實例化。
代碼塊16:determineAutowireCandidate
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
Class<?> requiredType = descriptor.getDependencyType();
// 1.根據@Primary註解來選擇最優解
String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
if (primaryCandidate != null) {
return primaryCandidate;
}
// 2.根據@Priority註解來選擇最優解
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
if (priorityCandidate != null) {
return priorityCandidate;
}
// Fallback
// 3.如果通過以上兩步都不能選擇出最優解,則使用最基本的策略
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateName = entry.getKey();
Object beanInstance = entry.getValue();
// 3.1 containsValue:首先如果這個beanInstance已經由Spring註冊過依賴關係,則直接使用該beanInstance作爲最優解,
// 3.2 matchesBeanName:如果沒有註冊過此beanInstance的依賴關係,則根據參數名稱來匹配,
// 如果參數名稱和某個候選者的beanName或別名一致,那麼直接將此bean作爲最優解
if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
matchesBeanName(candidateName, descriptor.getDependencyName())) {
return candidateName;
}
}
// 4.沒有找到匹配的候選者,則返回null
return null;
}
protected boolean matchesBeanName(String beanName, String candidateName) {
// candidateName與beanName相等 || beanName有別名與candidateName相等,則返回true
return (candidateName != null &&
(candidateName.equals(beanName) || ObjectUtils.containsElement(getAliases(beanName), candidateName)));
}
1.根據 @Primary 註解來選擇最優解,見代碼塊17詳解。
2.根據 @Priority 註解來選擇最優解,見代碼塊18詳解。
代碼塊17:determinePrimaryCandidate
protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String primaryBeanName = null;
// 1.遍歷所有候選者
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
// 2.判斷候選者bean是否使用了@Primary註解:如果candidateBeanName在當前BeanFactory中存在BeanDefinition,
// 則判斷當前BeanFactory中的BeanDefinition是否使用@Primary修飾;否則,在parentBeanFactory中判斷
if (isPrimary(candidateBeanName, beanInstance)) {
if (primaryBeanName != null) {
// 3.走到這邊primaryBeanName不爲null,代表標識了@Primary的候選者不止一個,則判斷BeanName是否存在於當前BeanFactory
// candidateLocal:candidateBeanName是否在當前BeanFactory的beanDefinitionMap緩存中
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
// primaryLocal:primaryBeanName是否在當前BeanFactory的beanDefinitionMap緩存中
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
if (candidateLocal && primaryLocal) {
// 3.1 如果當前BeanFactory中同一個類型的多個Bean,不止一個Bean使用@Primary註解,則拋出異常
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"more than one 'primary' bean found among candidates: " + candidates.keySet());
} else if (candidateLocal) {
// 3.2 candidateLocal爲true,primaryLocal爲false,則代表primaryBeanName是parentBeanFactory中的Bean,
// candidateBeanName是當前BeanFactory中的Bean,當存在兩個都使用@Primary註解的Bean,優先使用當前BeanFactory中的
primaryBeanName = candidateBeanName;
}
// 3.3 candidateLocal爲false,primaryLocal爲true,則代表primaryBeanName是當前BeanFactory中的Bean,
// candidateBeanName是parentBeanFactory中的Bean,因此無需修改primaryBeanName的值
} else {
// 4.primaryBeanName還爲空,代表是第一個符合的候選者,直接將primaryBeanName賦值爲candidateBeanName
primaryBeanName = candidateBeanName;
}
}
}
// 5.返回唯一的使用@Primary註解的Bean的beanName(如果都沒使用@Primary註解則返回null)
return primaryBeanName;
}
代碼塊18:determineHighestPriorityCandidate
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
// 用來保存最高優先級的beanName
String highestPriorityBeanName = null;
// 用來保存最高優先級的優先級值
Integer highestPriority = null;
// 1.遍歷所有候選者
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
// 2.拿到beanInstance的優先級
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (highestPriorityBeanName != null) {
// 3.如果之前已經有候選者有優先級,則進行選擇
if (candidatePriority.equals(highestPriority)) {
// 3.1 如果存在兩個優先級相同的Bean,則拋出異常
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
} else if (candidatePriority < highestPriority) {
// 3.2 使用優先級值較小的Bean作爲最優解(值越低,優先級越高)
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
} else {
// 4.第一次有候選者有優先級
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
// 5.返回優先級最高的bean的beanName
return highestPriorityBeanName;
}
代碼塊19:storeCache
public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) {
synchronized (mbd.constructorArgumentLock) {
// 將構造函數或工廠方法放到resolvedConstructorOrFactoryMethod緩存
mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
// constructorArgumentsResolved標記爲已解析
mbd.constructorArgumentsResolved = true;
if (this.resolveNecessary) {
// 如果參數需要解析,則將preparedArguments放到preparedConstructorArguments緩存
mbd.preparedConstructorArguments = this.preparedArguments;
} else {
// 如果參數不需要解析,則將arguments放到resolvedConstructorArguments緩存
mbd.resolvedConstructorArguments = this.arguments;
}
}
}
將解析出來的構造函數和參數放到緩存,在開頭的代碼塊4,就檢查過這些緩存。
總結
本文介紹了創建 bean 實例中的一個重要內容:創建一個新的 bean 實例。創建 bean 實例中剩下的:填充屬性、bean 實例初始化等內容,將在下篇文章介紹。