Spring框架原理之實(shí)例化bean和@Autowired實(shí)現(xiàn)原理方式
兩部分流程都較長,如果只對Bean的實(shí)例化感興趣只需要看到5.DefaultSingletonBeanRegistry小節(jié)即可,后面是分析@Autowired注解的實(shí)現(xiàn)原理。
一、UML類圖及流程分析
1.UML類圖組成
UML類圖組成如下:
這個圖中我們可以大致分為六個部分:
1、第一部分肯定是BeanDefinition的父類和子類組成的,這部分的組成有需要再細(xì)分一下,共可以分為六部分:
AttributeAccessor
接口:這個接口提供了setAttribute和getAttribute等操作屬性的方法提供給子類實(shí)現(xiàn);BeanMetadataElement
接口:該接口只提供了一個getSource方法,提供子類獲取源對象方法;BeanDefinition
接口:bean定義的直接接口,這個接口提供了常見的scope、lazy、dependsOn、initMethod和destroyMethod等屬性配置方法,規(guī)范了一個Spring管理的Bean必須實(shí)現(xiàn)哪些屬性;AnnotatedBeanDefinition
:注解bean定義,里面提供了兩個方法,一個是獲取注解元數(shù)據(jù),另一個是獲得方法元數(shù)據(jù);BeanDefinitionHolder
:該類和子類BeanComponentDefinition的作用便是持有bean的名字、別名和其對應(yīng)的BeanDefinition,可以注冊為內(nèi)部bean的占位符;BeanDefinitionBuilder
:普通BeanDefinition的構(gòu)造器,這里面可以構(gòu)造RootBeanDefinition、ChildBeanDefinition和GenericBeanDefinition等多個類型的bean定義,想要快速實(shí)例化一個bean定義可以用此類完成;
2、BeanDefinitionParser接口:從名字便可以看出來其大致作用,用來解析BeanDefinition的接口,其主要是被Spring的NamespaceHandlerSupport實(shí)現(xiàn)子類來完成諸如<component-scan/>和<annotation-config/>等XML標(biāo)簽的讀取解析去獲取Bean定義的;
3、BeanDefinitionRegistry接口:bean定義的注冊中心,該接口的實(shí)現(xiàn)子類將可以完成注冊、刪除和獲取bean定義等操作,Spring默認(rèn)實(shí)現(xiàn)的Bean工廠DefaultListableBeanFactory便實(shí)現(xiàn)了該接口來管理bean定義;
4、BeanWrapper接口:這部分的接口功能便是封裝一個bean實(shí)例,且提供為這個bean調(diào)用對應(yīng)的setter和getter方法,設(shè)置bean的具體成員屬性值;
5、@Autowired注解實(shí)現(xiàn)相關(guān)的類:如圖中的最右側(cè)部分的InjectionPoint實(shí)現(xiàn)層級和InjectionMetadata相關(guān)層級,這部分是存儲實(shí)現(xiàn)@Autowired注解功能的必要參數(shù),如class類型和這個class對象所需要的自動注入的對象;而DependencyDescriptor則保存了需要賦值的字段或者方法返回值和賦值的beanClass類型,隨后再根據(jù)DependencyDescriptor的具體子類類型判斷返回list、map、array或者單個的bean對象;
6.NamedBeanHolder:用來存儲beanName和已經(jīng)初始化完成的bean實(shí)例,這個對象在參數(shù)為class類型調(diào)用getBean時被使用。
2.流程分析
Spring工廠實(shí)例化bean時對象的變化流程圖:
我在分析該流程時將其分為了三個部分:
- 中間的核心部分:這部分的主要流程是在bean工廠的兩個抽象類AbstractBeanFactory和AbstractAutowireCapableBeanFactory中完成的,主要的功能便是通過bean的名稱調(diào)用getBean方法,隨后在這兩個類中完成初始化以及調(diào)用此過程中涉及到的接口,其中比較常用的便是FactoryBean和BeanPostProcessor兩個接口,諸如其它的Aware接口也是在這個流程調(diào)用的;
- 右邊的封裝部分:雖然這部分調(diào)用的getBean也是BeanFactory接口聲明的方法,但我們分析初始化Bean流程時可以把這個部分當(dāng)成額外的封裝部分,是對通過beanName獲取bean的一種基于便利性的額外封裝實(shí)現(xiàn)。這個流程主要是在DefaultListableBeanFactory類中完成的,其大致作用便是通過class類型獲取唯一的候選者beanName,因?yàn)橐粋€class類型可能會在工廠中匹配到多個beanName,因此需要做一些額外處理,當(dāng)獲得beanName之后再調(diào)用核心部分去實(shí)例化bean;
- 左邊的功能拓展部分:這部分的入口是在獲取到BeanWrapper之后,調(diào)用BeanPostProcessor實(shí)現(xiàn)類AutowiredAnnotationBeanPostProcessor來完成的。這部分的功能便是處理@Autowired注解,先通過BeanWrapper獲取bean的class對象,再判斷其字段和方法有哪些是被這個注解的,隨后再依次處理判斷,在獲得自動注入的這些實(shí)例時,將再次調(diào)用getBean,形成一個遞歸調(diào)用,完成bean的獲取和賦值到字段或方法上。
二、源碼分析
1.DefaultListableBeanFactory類實(shí)例化bean部分
先從外部額外封裝的getBean方法分析起,其關(guān)鍵源碼部分如下:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { @Override public <T> T getBean(Class<T> requiredType) throws BeansException { // 對外單個類參數(shù)獲取bean,將會調(diào)用后面帶有參數(shù)args的方法 return getBean(requiredType, (Object[]) null); } @Override public <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException { // 調(diào)用resolveBean方法解析bean Object resolved = resolveBean(ResolvableType .forRawClass(requiredType), args, false); // 如果返回的是nll,則代表Spring工廠中沒有class類型的bean信息 if (resolved == null) { throw new NoSuchBeanDefinitionException(requiredType); } return (T) resolved; } @Nullable private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) { // 流程圖中右側(cè)的最后一步,將resolveNamedBean方法返回的NamedBeanHolder // 類型判空,如果不為空則直接將內(nèi)部的beanInstance實(shí)例返回,在 // resolveNamedBean方法中執(zhí)行的是第三步,把ResolvableType轉(zhuǎn)為beanName NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull); if (namedBean != null) { return namedBean.getBeanInstance(); } // 如果從當(dāng)前的beanFactory中獲取不到bean的信息則從父類beanFactory中 // 獲取,依次遞歸下去,這里可以忽略這段代碼(正常情況下沒有層級關(guān)系) ... return null; } @Nullable private <T> NamedBeanHolder<T> resolveNamedBean( ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException { // 根據(jù)requiredType中的class類型獲取beanName集合,這里面將會判斷l(xiāng)ist // 集合beanDefinitionNames來獲取普通的bean候選者,判斷set集合 // manualSingletonNames中手動添加的單例對象,兩者都會判斷FactoryBean和 // 普通的bean對象,并選舉出來稱為候選者,具體流程不分析 String[] candidateNames = getBeanNamesForType(requiredType); // 如果獲取到的beanName是多個,則說明這一個class對應(yīng)多個bean if (candidateNames.length > 1) { List<String> autowireCandidates = new ArrayList<>(candidateNames.length); // 先判斷beanDefinitionMap集合中是否含有該candidateName // 如果有則后續(xù)進(jìn)行轉(zhuǎn)換到candidateNames數(shù)組 for (String beanName : candidateNames) { if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) { autowireCandidates.add(beanName); } } // 將List轉(zhuǎn)換為原來的String[]數(shù)組 if (!autowireCandidates.isEmpty()) { candidateNames = StringUtils .toStringArray(autowireCandidates); } } // 如果candidateNames數(shù)組長度為1,則說明class只有一個對應(yīng)的bean if (candidateNames.length == 1) { String beanName = candidateNames[0]; // 直接獲取0號位置的beanName,并調(diào)用getBean(beanName)方法初始化bean // 隨后將bean實(shí)例賦值到NamedBeanHolder中的beanInstance屬性中 // 以便該方法返回后直接返回beanInstance屬性對象 return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args)); } else if (candidateNames.length > 1) { Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length); // 對candidateNames進(jìn)行依次處理 for (String beanName : candidateNames) { // 如果是單例對象,即singletonObjects中含有此bean if (containsSingleton(beanName) && args == null) { // 直接先調(diào)用getBean(beanName)獲取bean實(shí)例 Object beanInstance = getBean(beanName); // 雖然放入到candidates集合中,以便后續(xù)返回具體的bean candidates.put(beanName, (beanInstance instanceof NullBean? null : beanInstance)); } else { // 如果是原型的,則先把class類型放到candidates中,后續(xù)返回時再 // 實(shí)例化返回 candidates.put(beanName, getType(beanName)); } } // 獲取主要的候選者,即最終的bean返回對象,即聲明對象時是否使用 // @Primary注解了,如果注解了則使用其中最后一個候選者 String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass()); // 如果判斷的主要候選者為空(沒有一個bean被@Primary注解) if (candidateName == null) { // 根據(jù)OrderComparator優(yōu)先級獲取優(yōu)先級最高的bean candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass()); } // 如果不為空 if (candidateName != null) { // 從前面組裝的candidates集合Map中獲取對應(yīng)的bean對象 // 這里獲取到的可能是bean實(shí)例化對象,也有可能是class對象 Object beanInstance = candidates.get(candidateName); // 如果beanInstance是空或者類型是class if (beanInstance == null || beanInstance instanceof Class) { // 調(diào)用getBean(candidateName)方法實(shí)例化bean beanInstance = getBean(candidateName, requiredType.toClass(), args); } // 使用NamedBeanHolder封裝bean實(shí)例并返回 return new NamedBeanHolder<>(candidateName, (T)beanInstance); } // 前面?zhèn)魅氲膎onUniqueAsNull值是false,因此如果到這里candidateName // 還是為null,則拋出異常沒有唯一的bean可返回 if (!nonUniqueAsNull) { throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet()); } } // 如果候選者candidateNames為0,則直接返回null return null; } }
這個類中主要方法棧為四層,調(diào)用這四個方法棧將會調(diào)用到其它的類中,如調(diào)用完之后將會返回已經(jīng)實(shí)例化的bean對象,在調(diào)用方法棧中將會調(diào)用到AbstractBeanFactory類中的getBean方法中。也就是說DefaultListableBeanFactory類只是對getBean(class)這個方法進(jìn)行了一層額外的封裝,最終還是調(diào)用到了AbstractBeanFactory類中,因此我自己把這部分流程劃為額外封裝實(shí)現(xiàn)。
2.AbstractBeanFactory抽象類
前面說過,調(diào)用getBean(class)最終實(shí)例化bean時將會調(diào)用到這個類中,且這個類是核心部分的入口,可以說是非常重要了。接下來我們看下其部分關(guān)鍵源碼:
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } @Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); } @Override public Object getBean(String name, Object... args) throws BeansException { // 這三個方法都是調(diào)用了doGetBean,唯一的不同便在于傳入的參數(shù)不一樣 // 但是name這個參數(shù)是必須的 return doGetBean(name, null, args, false); } protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 或許這個方法看起來會很長,但實(shí)際上可以把其分為五個功能大點(diǎn) // 一、使用aliasMap集合將傳入的name轉(zhuǎn)變成beanName final String beanName = transformedBeanName(name); Object bean; // 二、先從singletonObjects單例緩存集合中獲取bean對象,如果不為空 // 則直接返回賦值給sharedInstance對象如果為空則從singletonFactories集合 // 中獲取單例工廠類,并調(diào)用getObject獲取單例bean對象返回賦值 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { // 如果sharedInstance不為空,則調(diào)用getObjectForBeanInstance方法 // 判斷其是否被FactoryBean封裝的,如果是則調(diào)用該接口的getObject方法 // 獲取bean對象,如果不是則直接返回,其具體的方法流程略過,主要是 // 判斷FactoryBean接口的,有興趣的可以去看下,后面都會用到 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 判斷該beanName是否是原型且正在被創(chuàng)建的,如果是則拋出異常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 三、判斷該beanFactory的父類工廠是否含有該bean對象,此略過,最終 // 還是會跑到該方法的后續(xù)流程 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { ... } // typeCheckOnly傳入的是false,因此會進(jìn)入判斷 if (!typeCheckOnly) { // 該方法的作用便是將beanName添加到alreadyCreated集合中,標(biāo)記為 // 已經(jīng)實(shí)例化過beanName對應(yīng)的bean對象 markBeanAsCreated(beanName); } // 該try-catch塊將是實(shí)例化bean的地方,前面只是判斷 try { // 從mergedBeanDefinitions集合中獲取具體的BeanDefinition對象 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 判斷該bean定義是否合乎標(biāo)準(zhǔn),如非抽象類 checkMergedBeanDefinition(mbd, beanName, args); // 四、處理@DependsOn注解中的bean對象,在這里將會先實(shí)例化注解中 // 引用的bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { // 如果獲取的dependsOn不為空則依次遍歷其中引入的值 for (String dep : dependsOn) { // 判斷是否是循環(huán)依賴,如果是則拋出異常,所謂循環(huán)依賴則是 // @Bean注解的A方法使用@DependsOn依賴了@Bean注解的B方法 // 但是B方法又使用了@DependsOn依賴了A方法,形成死循環(huán) if (isDependent(beanName, dep)) { throw new BeanCreationException(); } // 跑到這里代表前面并沒有死循環(huán)依賴的發(fā)生,則把彼此相關(guān)的 // 依賴關(guān)系放入到dependentBeanMap中,因此第一次是絕對會 // 執(zhí)行到這里的 registerDependentBean(dep, beanName); try { // 實(shí)例化依賴的bean getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(); } } } // 五、判斷Bean是單例或是原型進(jìn)行相應(yīng)的實(shí)例化操作 if (mbd.isSingleton()) { // 如果是單例,則使用lambda實(shí)例化一個ObjectFactory對象傳入 // getSingleton方法實(shí)例化單例,這個方法也很重要,后續(xù)會分析 sharedInstance = getSingleton(beanName, () -> { try { // 實(shí)例化的ObjectFactory對象執(zhí)行的方法也很簡單 // 單純的調(diào)用createBean方法創(chuàng)造bean對象 return createBean(beanName, mbd, args); } catch (BeansException ex) { // 如果創(chuàng)造失敗則銷毀對象(清除緩存) destroySingleton(beanName); throw ex; } }); // 判斷這個bean是否被FactoryBean封裝 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // 如果bean是原型 Object prototypeInstance = null; try { // 記錄原型bean正在被創(chuàng)建,在前面會進(jìn)行判斷 beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { // 執(zhí)行完后將當(dāng)前創(chuàng)建的原型bean標(biāo)記去除 afterPrototypeCreation(beanName); } // 判斷這個bean是否被FactoryBean封裝 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { // 如果是其它類型的scope參數(shù) String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); // scope屬性不能為空 if (scope == null) { throw new IllegalStateException(); } try { // Scope接口是Spring提供給外部使用的,因此如果指定了 // 自定義的Scope實(shí)現(xiàn),調(diào)用里面的get方法將會執(zhí)行普通的 // 原型bean流程,只是開發(fā)者可以在Scope中對該bean進(jìn)行 // 額外的處理判斷 Object scopedInstance = scope.get(beanName, () -> { // 實(shí)際上ObjectFactory對象的操作流程和原型bean一模一樣 beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); // 判斷這個bean是否被FactoryBean封裝 bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } // 這部分是判斷如果要求的類型requiredType和獲得的bean類型不一致進(jìn)行 // 轉(zhuǎn)換的地方,正常使用是不會出現(xiàn)這種情況的,因此暫時略過 if (requiredType != null && !requiredType.isInstance(bean)) { ... } // 返回bean對象 return (T) bean; } }
實(shí)際上doGetBean這個方法流程可以分為五個部分流程,如下圖:
3.AbstractAutowireCapableBeanFactory抽象類
我們從上面的AbstractBeanFactory類已經(jīng)分析到了createBean方法了,由于創(chuàng)建和初始化bean的核心流程都在AbstractAutowireCapableBeanFactory類的幾個方法中,因此這個類的流程會比較多,大致流程可以看到下面的流程圖:
接下來我們看下其關(guān)鍵部分源碼:
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory { public <T> T createBean(Class<T> beanClass) throws BeansException { // AbstractBeanFactory并沒有調(diào)用這個方法,但是我們也可以看下 // 這個方法流程就是將beanClass封裝成Bean定義且設(shè)置成原型 RootBeanDefinition bd = new RootBeanDefinition(beanClass); bd.setScope(SCOPE_PROTOTYPE); bd.allowCaching = ClassUtils.isCacheSafe(beanClass, getBeanClassLoader()); return (T) createBean(beanClass.getName(), bd, null); } @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { // 真正創(chuàng)造bean的方法,這個方法大致可以分為三個部分 RootBeanDefinition mbdToUse = mbd; // 一、將beanName和bean定義解析成對應(yīng)的class類型 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); // 確定具體的beanClass類型 mbdToUse.setBeanClass(resolvedClass); } // 準(zhǔn)備方法覆蓋,無關(guān)緊要 try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(); } // 二、如果bean定義的beforeInstantiationResolved屬性為true // 則直接使用BeanPostProcessor對bean進(jìn)行處理,且處理后直接返回 // 不再使用Spring工廠的實(shí)例化流程,意味著Spring很多實(shí)例化中途的接口 // 都將不起作用,還沒見到過這種實(shí)例化方式的。這里面將會調(diào)用 // InstantiationAwareBeanPostProcessor接口的before方法,調(diào)用 // BeanPostProcessor接口的after方法 try { Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(); } try { // 三、調(diào)用doCreateBean方法實(shí)行真正創(chuàng)建bean流程 Object beanInstance = doCreateBean(beanName, mbdToUse, args); return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(); } } protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // 根據(jù)createBean方法的流程來看,其相當(dāng)于是外面再封裝了一層,用來解析 // beanClass屬性和提前使用BeanPostProcessor完成bean的實(shí)例化,真正的 // Spring實(shí)例化bean的流程其實(shí)是在這個方法中 // 在這個方法中共可以分為五個部分 BeanWrapper instanceWrapper = null; // 一、如果是單例對象,則把factoryBeanInstanceCache緩存清掉,同時獲取 // 緩存的BeanWrapper實(shí)例對象,單例對象(FactoryBean)在調(diào)用getType等 // 方法時將會被實(shí)例化后放到factoryBeanInstanceCache中,一般流程為null if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } // 如果instanceWrapper為null,則調(diào)用createBeanInstance實(shí)例化對象 // 在執(zhí)行完這個方法后bean對象才會被實(shí)例化 if (instanceWrapper == null) { // 具體實(shí)例化對象的地方,其大部分會調(diào)用instantiateBean方法利用反射來 // 完成bean的實(shí)例化 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 分別獲取實(shí)例化對象和class類型 final Object bean = instanceWrapper.getWrappedInstance(); Class<?> beanType = instanceWrapper.getWrappedClass(); if (beanType != NullBean.class) { mbd.resolvedTargetType = beanType; } // 二、允許程序在創(chuàng)建bean對象后再修改合并后的bean定義 synchronized (mbd.postProcessingLock) { if (!mbd.postProcessed) { try { // 里面會調(diào)用MergedBeanDefinitionPostProcessor的實(shí)現(xiàn)類 // 其也是BeanPostProcessor的一個子接口 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(); } mbd.postProcessed = true; } } // 三、快速緩存單例即使被BeanFactoryAware這樣的生命周期接口觸發(fā) // 以便能夠解決循環(huán)引用,前提是該單例bean正在創(chuàng)建中 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { // 將bean緩存到singletonObjects等單例集合中 // 大部分單例類都會調(diào)用到這里面,以便完成復(fù)雜的循環(huán)引用,當(dāng)所有的 // 實(shí)例被后續(xù)的流程初始化后,最終的單例將變成最終的形態(tài) addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; // 四、對bean進(jìn)行bean定義屬性填充及執(zhí)行一系列Spring初始化接口 try { // 構(gòu)造bean,這里面將會處理@Autowired和@Resource等操作bean成員屬性 // 的注解,也會分別調(diào)用setter方法去設(shè)置對應(yīng)的值,等下會分析 populateBean(beanName, mbd, instanceWrapper); // initializeBean方法將會執(zhí)行工廠接口的回調(diào),如aware系列接口、 // InitializingBean接口、initMethod和BeanPostProcessor的接口調(diào)用 // 這里調(diào)用BeanPostProcessor是真正的調(diào)用其接口after和before方法 exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex) .getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException(); } } // 五、判斷單例對象是否造成了兩次實(shí)例化導(dǎo)致單例對象出現(xiàn)不一致的現(xiàn)象 // 如果前面的提前存儲單例對象成立,則進(jìn)入(一般來說會進(jìn)入) if (earlySingletonExposure) { // 再次獲得提前放入的bean對象 Object earlySingletonReference = getSingleton(beanName, false); // 如果提前放入的bean對象引入不為空 if (earlySingletonReference != null) { // 如果經(jīng)過populateBean和initializeBean方法后bean引用沒變 // 則把早期的bean對象賦值給exposedObject對象 if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { // 如果經(jīng)過兩個初始化方法bean引用變了,則說明其它的bean已經(jīng) // 通過這兩個方法實(shí)例化成功了單例bean,且兩個單例bean不一致 // 拋出異常 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(); } } } } try { // 注冊需要銷毀的bean對象:實(shí)現(xiàn)了DisposableBean和AutoCloseable接口 // 或者指明了destroy方法 registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException(); } // 返回暴露的bean對象 return exposedObject; } protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { // 這個方法共可以分為四個部分 // 該方法的主要作用便是使用bean定義屬性值為BeanWrapper中的對象 // 填充對應(yīng)的值 if (bw == null) { // 如果bean定義為空且屬性值不為空則拋出異常,否則直接跳過該方法 if (mbd.hasPropertyValues()) { throw new BeanCreationException(); } else { return; } } // 一、根據(jù)InstantiationAwareBeanPostProcessor接口的 // postProcessAfterInstantiation方法返回值判斷是否 // 繼續(xù)執(zhí)行填充bean對象屬性 boolean continueWithPropertyPopulation = true; if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; // 根據(jù)其接口方法返回值判斷要不要繼續(xù)執(zhí)行后面的填充流程 if (!ibp.postProcessAfterInstantiation(bw .getWrappedInstance(), beanName)) { continueWithPropertyPopulation = false; break; } } } } // 為false則直接跳過 if (!continueWithPropertyPopulation) { return; } // 獲取bean定義中的屬性值 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); // 二、判斷bean的自動注入模式為AUTOWIRE_BY_NAME或AUTOWIRE_BY_TYPE // 一般都是使用默認(rèn)的后續(xù)流程,只有特殊指定才會進(jìn)入這兩步,這兩個 // 方法的作用便是把當(dāng)前的bean定義根據(jù)參數(shù)名字或者類型從bean工廠中 // 獲取對應(yīng)的bean,并且保存到newPvs對象中,如mybatis的mapper便是 // 使用type類型獲取到sqlSessionTemplate和sqlSessionFactory兩個bean的 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // 根據(jù)autotowire的名稱(如適用)添加屬性值 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // 根據(jù)自動裝配的類型(如果適用)添加屬性值 if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } // 判斷是否有InstantiationAwareBeanPostProcessor接口,有為true boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); // 是否需要檢查依賴,一般而言此值默認(rèn)為false,暫時忽略 boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); // 三、如果有InstantiationAwareBeanPostProcessor接口則進(jìn)入 PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } // 依次獲取InstantiationAwareBeanPostProcessor接口調(diào)用其 // postProcessProperties方法和postProcessPropertyValues方法 // 并獲得這兩個方法的返回值,以便后續(xù)使用 // 解析@Autowired注解并賦值便是在段方法中完成的,后面會分析 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); // 此方法流程已被官方刪除,原來的流程實(shí)際調(diào)用的也是 // postProcessProperties,因此這一段可以忽略 if (pvsToUse == null) { ... } pvs = pvsToUse; } } } // 略過 if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } // 四、如果返回的pvs不為空,則說明這些屬性需要設(shè)置到BeanWrapper中 if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } } protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { // 這個方法共可以分為四個部分 // 一、調(diào)用invokeAwareMethods方法,從名字就可以看出來,這個方法是用來 // 調(diào)用Aware系列接口,包括BeanNameAware、BeanClassLoaderAware和 // BeanFactoryAware,System.getSecurityManager()語句只是為了判斷當(dāng)前 // 系統(tǒng)有沒有權(quán)限調(diào)用Aware接口 if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; // 二、調(diào)用BeanPostProcessor接口的postProcessBeforeInitialization方法 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } try { // 三、這里面會調(diào)用InitializingBean接口的afterPropertiesSet方法 // 且會調(diào)用指定的initMethod和destroyMethod方法 invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException(); } // 四、調(diào)用BeanPostProcessor接口的postProcessAfterInitialization方法 if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } // 返回經(jīng)過Aware、init、destroy、BeanPostProcessor接口的before和after // 系列接口方法處理過的bean對象 return wrappedBean; } }
想要理清楚這里面的流程,還是需要自己親自走一遍創(chuàng)建的源碼流程,否則不管看多少次流程分析到頭來也還是會生疏忘記。
4.DefaultSingletonBeanRegistry類
這個類主要負(fù)責(zé)單例對象的緩存和一些判斷。接下來看下其部分關(guān)鍵源碼:
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { // 保存單例對象的Map集合 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); // 保存單例對象和其對應(yīng)的ObjectFactory集合 private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 提前緩存單例的集合 private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 正在創(chuàng)建單例的集合 private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16)); // 注冊成功的單例bean對象 private final Set<String> registeredSingletons = new LinkedHashSet<>(256); @Override @Nullable public Object getSingleton(String beanName) { // 在前面創(chuàng)建bean的流程中調(diào)用的便是這個方法 return getSingleton(beanName, true); } protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 這個方法實(shí)際上只是從緩存中獲取單例對象 Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { synchronized (this.singletonObjects) { // 進(jìn)入到這里說明緩存對象沒有命中 singletonObject = this.earlySingletonObjects.get(beanName); // 再判斷提前緩存的單例對象集合能不能命中 if (singletonObject == null && allowEarlyReference) { // 如果提前緩存的單例對象也無法命中則從singletonFactories // 集合中查找對應(yīng)的ObjectFactory對象,如果不為空則調(diào)用其 // getObject初始化bean對象 ObjectFactory<?> singletonFactory = this .singletonFactories.get(beanName); if (singletonFactory != null) { // 調(diào)用getObject初始化單例bean對象,并緩存起來 singletonObject = singletonFactory.getObject(); this.earlySingletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); } } } } return singletonObject; } protected void addSingleton(String beanName, Object singletonObject) { // 添加單例說明這個單例對象已經(jīng)完全初始化完成,因此可以把提前緩存在 // earlySingletonObjects和singletonFactories集合的bean刪除,直接放進(jìn) // singletonObjects和registeredSingletons集合 synchronized (this.singletonObjects) { this.singletonObjects.put(beanName, singletonObject); this.singletonFactories.remove(beanName); this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { // 這個方法在前面初始化單例bean時會被調(diào)用,且singletonFactory對象 // 是由lambda實(shí)例化的一個對象,里面只有一個調(diào)用createBean方法語句 synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); // 先判斷單例bean緩存有沒有這個bean,如果有就直接返回,沒有則進(jìn)入判斷 if (singletonObject == null) { // 該單例bean有另外一個線程正在初始化中拋出異常 if (this.singletonsCurrentlyInDestruction) { throw new BeanCreationNotAllowedException(); } // 記錄單例beanName正在實(shí)例化中 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 調(diào)用getObject方法(實(shí)際為調(diào)用createBean方法,因?yàn)檫@個 // 對象方法中只有調(diào)用createBean方法語句) singletonObject = singletonFactory.getObject(); newSingleton = true; } catch (IllegalStateException ex) { singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { throw ex; } } catch (BeanCreationException ex) { if (recordSuppressedExceptions) { for (Exception suppressedException : this.suppressedExceptions) { ex.addRelatedCause(suppressedException); } } throw ex; } finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } // 標(biāo)記beanName已經(jīng)創(chuàng)建完成 afterSingletonCreation(beanName); } // 如果創(chuàng)建過程中為拋出異常則添加到單例緩存中 if (newSingleton) { addSingleton(beanName, singletonObject); } } // 返回單例對象 return singletonObject; } } }
5.AutowiredAnnotationBeanPostProcessor類
這個類是BeanPostProcessor接口的實(shí)現(xiàn)類,是完成@Autowired注解原理的地方,接下來看到其關(guān)鍵源碼:
public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { // 這個集合中保存了@Autowired和@Value注解 private final Set<Class<? extends Annotation>> autowiredAnnotationTypes = new LinkedHashSet<>(4); @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { // 找到這個bean哪些字段和方法需要自動注入 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs); try { // 調(diào)用注入流程 metadata.inject(bean, beanName, pvs); } catch (BeanCreationException ex) { throw ex; } catch (Throwable ex) { throw new BeanCreationException(); } return pvs; } private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) { // 返回到類名作為緩存鍵,以便向后兼容自定義調(diào)用者。 String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName()); // 首先對并發(fā)映射進(jìn)行快速檢查,使用最小的鎖定。 InjectionMetadata metadata = this .injectionMetadataCache.get(cacheKey); // 先進(jìn)行一層緩存判斷,但是不上鎖,可以讓一大批線程通過這個判斷方法 // 完成是否需要刷新的判斷,而不需要阻塞線程 if (InjectionMetadata.needsRefresh(metadata, clazz)) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(cacheKey); // 進(jìn)行第二次判斷,此時判斷的對象是需要刷新的,且并發(fā)量高只有幾個 // 線程會同時到這里,保證了最小粒度線程判斷,這種使用方法和單例對 // 象的兩重判斷原理一樣,都是為了避免同一個class執(zhí)行多次if塊里面 // 的流程 if (InjectionMetadata.needsRefresh(metadata, clazz)) { if (metadata != null) { metadata.clear(pvs); } // 根據(jù)類獲取需要自動注入的字段和方法 metadata = buildAutowiringMetadata(clazz); // 放入緩存 this.injectionMetadataCache.put(cacheKey, metadata); } } } return metadata; } private InjectionMetadata buildAutowiringMetadata( final Class<?> clazz) { // 看起來這個方法很長,但實(shí)際上只執(zhí)行了兩個有用的邏輯 List<InjectionMetadata.InjectedElement> elements = new ArrayList<>(); Class<?> targetClass = clazz; do { // 當(dāng)前類所需要自動注入的元素集合 final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>(); // 依次遍歷字段判斷哪些字段擁有autowiredAnnotationTypes集合中的注解 // 如果有的話則將其封裝添加到currElements集合中 ReflectionUtils.doWithLocalFields(targetClass, field -> { AnnotationAttributes ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { return; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } }); // 類似遍歷字段的,這里只是遍歷了方法,其它流程一樣 ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver .findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } AnnotationAttributes ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils .getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { return; } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils .findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } }); // 添加到需要返回的集合elements中 elements.addAll(0, currElements); // 再遍歷父類,依次循環(huán) targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); // 封裝成注入元數(shù)據(jù)類型 return new InjectionMetadata(clazz, elements); } }
可以看到這個類執(zhí)行的操作只是獲取該bean被@Autowired和@Value注解的字段和方法,然后使用InjectedElement和InjectionMetadata對象封裝。
6.InjectionMetadata類
從上面的流程我們知道了會調(diào)用到這個類的inject方法中來,接下來我們看下其部分關(guān)鍵源碼:
public class InjectionMetadata { // 需要注入的bean class類型 private final Class<?> targetClass; // 該bean class需要注入的字段和方法集合 private final Collection<InjectedElement> injectedElements; public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Collection<InjectedElement> checkedElements = this.checkedElements; Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements); // 如果需要注入的字段和方法集合迭代器不為空 if (!elementsToIterate.isEmpty()) { // 依次循環(huán)調(diào)用元素的inject方法, for (InjectedElement element : elementsToIterate) { element.inject(target, beanName, pvs); } } } }
7.AutowiredFieldElement內(nèi)部類
這個類是InjectionMetadata.InjectedElement內(nèi)部類的子類實(shí)現(xiàn),主要針對的是需要自動注入字段的執(zhí)行,需要注意的是這個類也是AutowiredAnnotationBeanPostProcessor的內(nèi)部類實(shí)現(xiàn)。接下來我們看其關(guān)鍵源碼部分:
private class AutowiredFieldElement extends InjectionMetadata.InjectedElement { @Override protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable { Field field = (Field) this.member; Object value; // 先判斷是否已經(jīng)被緩存了 if (this.cached) { // 如果緩存了就直接從bean工廠中獲取或直接返回cachedFieldValue的值 value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { // 沒有緩存則將字段封裝成DependencyDescriptor對象 DependencyDescriptor desc = new DependencyDescriptor(field, this.required); // 設(shè)置對應(yīng)的bean類型 desc.setContainingClass(bean.getClass()); Set<String> autowiredBeanNames = new LinkedHashSet<>(1); TypeConverter typeConverter = beanFactory.getTypeConverter(); try { // 直接調(diào)用bean工廠的resolveDependency方法解析這個bean涉及的 // 依賴bean,并且最終返回bean值 value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); } catch (BeansException ex) { throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex); } synchronized (this) { // 如果未緩存,則說明是第一次 if (!this.cached) { // 如果返回的值不為空 if (value != null || this.required) { this.cachedFieldValue = desc; // 注冊這個bean和自動注入值的依賴關(guān)系 registerDependentBeans(beanName, autowiredBeanNames); if (autowiredBeanNames.size() == 1) { // 如果返回值只有一個,則封裝成對象類型 // ShortcutDependencyDescriptor緩存起來 String autowiredBeanName = autowiredBeanNames .iterator().next(); // 從bean工廠中判斷確實(shí)這個value返回值存在且類型正確 if (beanFactory.containsBean(autowiredBeanName) && beanFactory.isTypeMatch(autowiredBeanName, field.getType())) { // 緩存起來 this.cachedFieldValue = new ShortcutDependencyDescriptor( desc, autowiredBeanName, field.getType()); } } } else { this.cachedFieldValue = null; } // 設(shè)置為緩存狀態(tài) this.cached = true; } } } if (value != null) { ReflectionUtils.makeAccessible(field); // 利用映射把獲得的value值set到字段上 field.set(bean, value); } } }
這個類的作用便是緩存且調(diào)用bean工廠獲取需要注入的bean值,然后set到相應(yīng)的字段或者方法上。
8.DefaultListableBeanFactory類處理@Autowired注解
我們可以先分析一下處理自動注入依賴的方法流程圖:
直入主題,其關(guān)鍵部分源碼如下:
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable { @Override @Nullable public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { // 這個方法也是一個中間方法,前面兩個判斷不用管,只需要看到最后一個即可 descriptor.initParameterNameDiscovery(getParameterNameDiscoverer()); if (Optional.class == descriptor.getDependencyType()) { return createOptionalDependency(descriptor, requestingBeanName); } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) { return new DependencyObjectProvider(descriptor, requestingBeanName); } else if (javaxInjectProviderClass == descriptor.getDependencyType()){ return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName); } else { // 正常流程直接看到這一步來即可,調(diào)用返回的result一般情況下為null Object result = getAutowireCandidateResolver() .getLazyResolutionProxyIfNecessary( descriptor, requestingBeanName); if (result == null) { // 因此一般情況下會調(diào)用這個方法獲取bean對象,這個方法也是需要重點(diǎn) // 分析的 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); } return result; } } @Nullable public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException { // 像前面介紹的流程一樣,將DependencyDescriptor對象轉(zhuǎn)換為InjectionPoint // 這個方法也很長,需要慢慢分析,大致可以分為六個部分 InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor); try { // 一、如果是ShortcutDependencyDescriptor類型的則會直接調(diào)用getBean // 方法,但是一般都是DependencyDescriptor類型,大部分情況可忽略 Object shortcut = descriptor.resolveShortcut(this); if (shortcut != null) { return shortcut; } // 二、從descriptor對象的注解中嘗試獲取值,只有當(dāng)方法返回的類型是 // QualifierAnnotationAutowireCandidateResolver才會這樣做,默認(rèn)的 // 是ContextAnnotationAutowireCandidateResolver類型,此流程可忽略 Class<?> type = descriptor.getDependencyType(); Object value = getAutowireCandidateResolver() .getSuggestedValue(descriptor); if (value != null) { // 如果獲得的值是String類型,則需要使用使用Expression語法獲取值 if (value instanceof String) { String strVal = resolveEmbeddedValue((String) value); BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null); // 實(shí)際會調(diào)用Expression語法獲取值 value = evaluateBeanDefinitionString(strVal, bd); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); try { // 對返回的值進(jìn)行類型轉(zhuǎn)換 return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor()); } catch (UnsupportedOperationException ex) { return (descriptor.getField() != null ? converter.convertIfNecessary(value, type, descriptor.getField()) : converter.convertIfNecessary(value, type, descriptor.getMethodParameter())); } } // 三、解決自動注入的值為數(shù)組、Map集合或者Collection集合,如果是 // 數(shù)組則直接把bean工廠中這個類型的按照Comparator排序返回;如果是 // Collection集合且類型為接口則獲取對應(yīng)的bean對象且進(jìn)行類型轉(zhuǎn)換和 // 排序處理;如果是Map則直接key為beanName,value為這個類型的對象; // 這幾個類型descriptor對象將被封裝成MultiElementDescriptor類型 // 這個類型后續(xù)將會調(diào)用bean工廠的getBean方法,獲取集合需要的bean對象 // 這里實(shí)際會調(diào)用到findAutowireCandidates方法中,只是中間解析了上面 // 所說的三種集合類型,findAutowireCandidates這個方法等下分析 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 四、直接調(diào)用findAutowireCandidates方法獲取Map集合key為beanName // Object為bean對象 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { // 如果為空且required為true,則檢查beanDefinitionNames中 // 是否有該類型的bean,如果沒有則拋出異常 if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } return null; } String autowiredBeanName; Object instanceCandidate; // 五、處理獲取到的候選matchingBeans集合,分為單個和多個,數(shù)量為0 // 的情況以前面已經(jīng)處理了 if (matchingBeans.size() > 1) { // 如果候選有多個,則使用Comparator獲取最高優(yōu)先級的候選者 // 或者beanName一模一樣的bean對象 autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); if (autowiredBeanName == null) { // 如果候選者為空且required為true,則檢查并拋出異常 if (isRequired(descriptor) || !indicatesMultipleBeans(type)) { return descriptor.resolveNotUnique(descriptor .getResolvableType(), matchingBeans); } else { // required為false則直接返回null return null; } } // 獲取候選者 instanceCandidate = matchingBeans.get(autowiredBeanName); } else { // 僅有一個,直接獲取第一個的key和值 Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); autowiredBeanName = entry.getKey(); instanceCandidate = entry.getValue(); } // 六、對獲取到的單個候選者進(jìn)行處理 if (autowiredBeanNames != null) { autowiredBeanNames.add(autowiredBeanName); } // 如果從候選者們獲取到的的類型是class,則需要調(diào)用resolveCandidate // 方法來通過class類型實(shí)例化bean,resolveCandidate方法會直接調(diào)用 // bean工廠的getBean方法;如果不是class類型,那一定是實(shí)例化好的 // bean對象 if (instanceCandidate instanceof Class) { instanceCandidate = descriptor .resolveCandidate(autowiredBeanName, type, this); } Object result = instanceCandidate; // 進(jìn)行required參數(shù)的判斷,不滿足拋異常 if (result instanceof NullBean) { if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } result = null; } // 判斷獲取的類型和值是否一樣,不一樣則拋出異常 if (!ClassUtils.isAssignableValue(type, result)) { throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass()); } return result; } finally { ConstructorResolver.setCurrentInjectionPoint( previousInjectionPoint); } } protected Map<String, Object> findAutowireCandidates( @Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) { // 在獲取到beanName和這個bean的class類型后將會調(diào)用這個方法來獲取 // 這個class類型的一系列候選者,該方法一共可以分為三個部分 // 一、或者這個beanName的候選者名稱 String[] candidateNames = BeanFactoryUtils .beanNamesForTypeIncludingAncestors( this, requiredType, true, descriptor.isEager()); Map<String, Object> result = new LinkedHashMap<>(candidateNames.length); // 一、判斷resolvableDependencies集合中類型相同的對象 // 遍歷判斷已經(jīng)解析過的依賴對象,如果類型相同或者是需要實(shí)例化的父類 // 則將其添加到result中 for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) { Class<?> autowiringType = classObjectEntry.getKey(); if (autowiringType.isAssignableFrom(requiredType)) { Object autowiringValue = classObjectEntry.getValue(); autowiringValue = AutowireUtils .resolveAutowiringValue(autowiringValue, requiredType); if (requiredType.isInstance(autowiringValue)) { result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue); break; } } } // 二、對前一步獲取到的對象和候選者名稱進(jìn)行遍歷處理,處理后的結(jié)果將會添加 // 到result中addCandidateEntry方法后面會分析 for (String candidate : candidateNames) { if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) { addCandidateEntry(result, candidate, descriptor, requiredType); } } // 三、如果需要返回的候選者結(jié)果集為空,正常情況下前面獲取到的result為空 // 這個方法塊中獲取到的result也為空,但是其具體作用場景尚不清楚 // 因此暫時略過 if (result.isEmpty()) { // 如果第一輪沒有找到任何內(nèi)容,考慮回退匹配對應(yīng)的名稱對象 boolean multiple = indicatesMultipleBeans(requiredType); ... } return result; } private void addCandidateEntry(Map<String, Object> candidates, String candidateName, DependencyDescriptor descriptor, Class<?> requiredType) { // 解決不同的descriptor對象 if (descriptor instanceof MultiElementDescriptor) { // MultiElementDescriptor類型則直接調(diào)用bean工廠的getBean方法獲取 // 處理化bean對象 Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this); if (!(beanInstance instanceof NullBean)) { candidates.put(candidateName, beanInstance); } } else if (containsSingleton(candidateName) || (descriptor instanceof StreamDependencyDescriptor && ((StreamDependencyDescriptor) descriptor).isOrdered())) { // 如果是單例或者是StreamDependencyDescriptor類型,也是調(diào)用 // bean工廠的getBean方法獲取處理化bean對象,只是value可能為NullBean Object beanInstance = descriptor.resolveCandidate(candidateName, requiredType, this); candidates.put(candidateName, (beanInstance instanceof NullBean ? null : beanInstance)); } else { // 無法識別處理的則將String名字編程對象的class對象,以方便后續(xù)流程 // 直接初始化class類型對應(yīng)的bean對象 candidates.put(candidateName, getType(candidateName)); } } }
至此,兩個流程的分析便已經(jīng)結(jié)束了,要想了解其具體流程還是需要自己去走一遍源碼,并且仔細(xì)分析一下各個方法的搭配和前后流程關(guān)系,否則不管看多少遍都是無用功。
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring Boot項目如何同時支持HTTP和HTTPS協(xié)議的實(shí)現(xiàn)
這篇文章主要介紹了Spring Boot項目如何同時支持HTTP和HTTPS協(xié)議的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10BigDecimal divide除法除不盡報錯的問題及解決
這篇文章主要介紹了BigDecimal divide除法除不盡報錯的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06Springboot JPA 枚舉Enum類型存入到數(shù)據(jù)庫的操作
這篇文章主要介紹了Springboot JPA 枚舉Enum類型存入到數(shù)據(jù)庫的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01@Slf4j?如何實(shí)現(xiàn)日志輸入到外部文件
這篇文章主要介紹了@Slf4j?如何實(shí)現(xiàn)日志輸入到外部文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12ssm框架Springmvc文件上傳實(shí)現(xiàn)代碼詳解
這篇文章主要介紹了ssm框架Springmvc文件上傳實(shí)現(xiàn)代碼詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07Java實(shí)現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的示例
這篇文章主要介紹了Java實(shí)現(xiàn)Word/Pdf/TXT轉(zhuǎn)html的示例,幫助大家方便的進(jìn)行文件格式轉(zhuǎn)換,完成需求,感興趣的朋友可以了解下2020-11-11