做爲一個Spring開發者對@Autowired註解一定是很是瞭解了, 顧名思義自動裝配,應該是Spring會自動將咱們標記爲@Autowired的元素裝配好,與其猜想不如看看它的定義:java
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { boolean required() default true; }
很明顯這個註解能夠用到構造器,變量域,方法,註解類型上。文檔上這樣描述:將一個構造器,變量域,setter方法,config方法標記爲被Spring DI 工具自動裝配。換句話說,咱們視圖從bean 工廠中獲取一個bean時,Spring會自動爲咱們裝配該bean中標記爲@Autowired的元素,而無需咱們手動完成。這些相信你們都明白,但問題是,Spring是怎樣作到的?在Spring MVC中怎樣作到的?何時進行的自動裝配?下面咱們就來探究下這些問題。ios
在@Autowired的定義中有下面一段話:數組
Note that actual injection is performed through a BeanPostProcessor which in turn means that you cannot use @Autowired to inject references into BeanPostProcessor or BeanFactoryPostProcessor types. Please consult the javadoc for the AutowiredAnnotationBeanPostProcessor class (which, by default, checks for the presence of this annotation).
意思是:實際的注入裝配動做是由BeanPostProcessor執行的,翻過來講你不能將@Autowired註解用於BeanPostProcessor或BeanFactoryPostProcessor類型上。請查看AutowiredAnnotationBeanPostProcessor文檔(默認狀況下,被用來檢查@Autowired註解)。緩存
文檔說的很清楚了,BeanPostProcessor來執行自動裝配,而且默認狀況下使用AutowiredAnnotationBeanPostProcessor實現類完成。那咱們不妨看一下他們的定義:安全
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
BeanPostProcessor就一個回調接口,定義了兩個方法聲明,一個是實例化前被調用,一個是實例化後被調用,沒啥好看的,咱們直接看看它的實現類AutowiredAnnotationBeanPostProcessor:多線程
BeanPostProcessor implementation that autowires annotated fields, setter methods and arbitrary config methods. Such members to be injected are detected through a Java 5 annotation: by default, Spring's @Autowired and @Value annotations.Also supports JSR-330's @Inject annotation, if available, as a direct alternative to Spring's own @Autowired. Note: A default AutowiredAnnotationBeanPostProcessor will be registered by the "context:annotation-config" and "context:component-scan" XML tags. NOTE: Annotation injection will be performed before XML injection; thus the latter configuration will override the former for properties wired through both approaches.
上面是AutowiredAnnotationBeanPostProcessor類的描述文檔摘要,大體意思是:這是BeanPostProcessor接口的一個實現,用來自動裝配註解的變量域,setter方法和任意的config方法。這些被注入的元素是經過檢測Java 5的註解完成的:默認狀況下是@Autowired和@Value註解。一樣也支持JSR-330的@Inject註解。而且,<context:annotation-config/>和<context:component-scan/>XML標籤能夠默認註冊AutowiredAnnotationBeanPostProcessor到bean工廠中。最後,註解注入會在XML注入以前執行;所以後面的配置會覆蓋前面已經裝配好的元素。app
是否是很清楚了?Spring的文檔老是這麼詳細,要麼說是教科書呢,廢話很少說,咱們纔剛進正題呢,既然咱們清楚了是AutowiredAnnotationBeanPostProcessor實例執行了自動裝配,那麼它作了什麼呢?框架
在正式查看源碼前,我先大體的講一下整個裝配的過程,以便後面理解起來輕鬆些。其實總體思路仍是很簡單的,咱們舉個簡單的例子:ide
//==================================Controller @Controller public class SimpleController { @Autowired private SimpleService simpleService; } //==================================Service @Service("simpleService") public class SimpleServiceImpl implements SimpleService { @Autowired private SimpleDao simpleDao; } //===================================Repository @Repository("simpleDao") public class SimpleDaoImpl implements SimpleDao { }
1)在某一時刻Spring調用了 Bean工廠 的 getBean(beanName) 方法。beanName多是simpleController,或者simpleService,simpleDao,順序不要緊(由於後面會有依賴關係的處理)。咱們假設simpleController吧。工具
2)getBean方法首先會調用Bean工廠中定義的getSingleton(beanName)方法,來判斷是否存在該名字的bean單例,若果存在則返回,方法調用結束。
3)不然,Spring會檢查是否存在父工廠,若是有則返回,方法調用結束。
4)不然,Spring 會檢查該bean 定義(BeanDefinition實例,用來描述Bean結構,上篇文章講到過,component-scan 掃描後,就是將beanDefinition實例放入Bean工廠,此時Bean尚未被實例化。)是否有依賴關係,若是有,執行1)步,獲取依賴的bean實例。
5)不然,Spring會嘗試建立這個bean實例,建立實例前,Spring會檢查肯定調用的構造器,並實例化該Bean。
6)實例化完成後,Spring會調用Bean工廠的populateBean方法來填充bean實例的屬性,也就是咱們前面提到的自動轉配了。populateBean方法即是調用了BeanPostProcessor實例來完成屬性元素的自動裝配工做。
7)在元素裝配過程當中,Spring會檢查被裝配的屬性是否存在自動裝配的其餘屬性,而後遞歸調用getBean方法,直到全部@Autowired的元素都被裝配完成。如在裝配simpleController中的simpleService屬性時,發現SimpleServiceImpl實例中存在@Autowired屬性simpleDao,而後調用getBean(simpleDao)方法,一樣會執行1)-7)整個過程。因此能夠當作一個遞歸過程。
8)裝配完成後,Bean工廠會將全部的bean實例都添加到工廠中來。
注:咱們知道Spring MVC是多線程單實例的MVC框架,就是說,對於同一個Controller,只會生成一個實例來處理全部的請求,所以bean實例只會實例化一次,並被存放在工廠中,以供其餘請求使用。
好了,大體瞭解整個流程後咱們看一下Spring的具體行爲吧。
前面屢次提到了Bean工廠,但一直沒有說它究竟是個什麼,這裏咱們就完全弄清楚吧,省的雲裏霧裏,這樣咱們後面講到Bean工廠就不會暈了。看過上一篇博客(<context:component-scan/>)的朋友可能記得DefaultListableBeanFactory這個類,當時是它保存了掃描到的組件--Bean Definition實例。那他是不是咱們所說的Bean工廠呢?是否保存了Bean實例呢?答案是:對。
咱們能夠看到DefaultLiableBeanFactory繼承自DefaultSingletonBeanRegistry,AbstractBeanFactory,AbstractAutowireCapableBeanFactory。下面就列出了一下相關的Bean工廠中的屬性和方法:
//========================================================================================== //==============================DefaultListableBeanFactory================================ //========================================================================================== //beanName-beanDefinition 的映射表 private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64); //beanName 列表 private final List<String> beanDefinitionNames = new ArrayList<String>(); //========================================================================================== //=============================AbstractBeanFactory================================= //========================================================================================== //註冊了全部的BeanPostProcessor實例,包括前面提到的用來處理@Autowired註解的 //AutowiredAnnotationBeanPostProcessor private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<BeanPostProcessor>(); //可能存在的父親Bean工廠 private BeanFactory parentBeanFactory; //========================================================================================== //==============================DefaultSingletonBeanRegistry================================ //========================================================================================== //beanName--bean單例的映射表 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64); //註冊過的beanName集合 private final Set<String> registeredSingletons = new LinkedHashSet<String>(64); //beanName與該bean所依賴的Beans集合的映射表,如simpleDao依賴與simpleService,若是還有其餘 service使用該Dao,如simpleService2那麼是simpleDao->[simpleService,simpleService2] private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<String, Set<String>>(64); //剛好與上面相反,beanName與該bean所包含的beans的集合映射表,如simpleController->[simpleService] private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<String, Set<String>>(64);
能夠看到Bean工廠中即存有bean definition的映射表,也存有bean name的別表,以及bean實例的映射表,還有依賴關係圖。理解了這個對下面的實例化以及裝配過程會有很大幫助。
下面咱們就從頭至尾看一下整個的實例化和裝配過程:
public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } @SuppressWarnings("unchecked") protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException { //去掉工廠bean的前綴或者將別名轉化爲規範名 final String beanName = transformedBeanName(name); Object bean; // 檢查是否有已經註冊的bean實例 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { //若是是工廠bean,獲取工廠bean建立的bean bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //判斷是否有父工廠,而且其中是否存在該bean實例? BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } if (!typeCheckOnly) { markBeanAsCreated(beanName);//將該beanName標記爲已經實例化 } //獲取該beanName對應的BeanDefinition實例,從上面說到的beanDefinitionMap表中查找 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); //判斷是否有依賴bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dependsOnBean : dependsOn) { getBean(dependsOnBean);//若是有依賴bean,遞歸調用getBean方法 registerDependentBean(dependsOnBean, beanName);//將依賴關係保存到 上面提到的 //dependBeanMap和dependencyForBeanMap中。 } } // 真正的開始牀架bean實例了。激動吧 if (mbd.isSingleton()) {//beanDefinition中指定該實例爲單例 //去工廠中獲取單例,若是沒有建立一個,而後添加到工廠中,不然直接返回 sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) {//原型方式,每次都建立一個新的實例 Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else {//其餘方式,如目前主體無關,不贅述 } } return (T) bean; }
這個方法好長,真的好長,我還刪除了一些與當前主體無關的代碼呢,好吧,不要被嚇住,若是是本身寫的代碼,再長都很容易弄懂,類的繼承關係再複雜都能輕車熟路,那是由於咱們都清楚的知道每一行的用意,看別人的代碼同樣,多看幾遍就明白了,再複雜都同樣。
首先Spring會檢查beanName,獲取規範的beanName,而後它會檢查是否存在已經註冊的單例(查詢上面提到的singletonObjects映射表),若是有的話就直接返回了,一切就結束了,不然的話,會查看是否存在父工廠,若是有調用父工廠的getBean方法,若是沒有呢?
好吧那就要着手建立實例了,首先查看beanDefinitionMap查找該beanName對應的beanDefinition實例,而後根據該實例判斷是否存在依賴關係,若是存在在遞歸的調用getBean方法,直到全部的依賴關係都正確的實例化和裝配完成,而且將這些依賴關係保存到上面提到的dependencyForBeanMap 和dependentBeanMap中。
接下來,Spring查看BeanDefinition來肯定該Bean應該是單例方式建立仍是原型方式建立?若是是單例的話,Spring會調用getSingleton方法查找或建立一個單例(下面會詳聊),若是是原型的話,每次調用getBean方法都會建立一個新的實例,看上面代碼便會一清二楚了。
那下面咱們就看看這個getSingleton方法作了什麼?
public Object getSingleton(String beanName, ObjectFactory singletonFactory) { //這不就是上面說的bean實例映射表嗎?哈,被同步了,保證線程安全啊 synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) {//第一次建立固然是空 beforeSingletonCreation(beanName);//這個是看看當前的beanName是否在排除列表中,若是是 //則拋出異常 boolean recordSuppressedExceptions = (this.suppressedExceptions == null); try {//這裏調用了上面的匿名內部類的getObject方法了,實則調用了createBean方法 singletonObject = singletonFactory.getObject(); }//這不,添加到了singleObjects映射表中了,以備下次使用 addSingleton(beanName, singletonObject); } return (singletonObject != NULL_OBJECT ? singletonObject : null); } }
這裏稍微清晰了,查看singletonObjects映射表,看是否存在已經註冊的單例,若是沒有調用createBean方法建立一個,而且註冊到singletonObjects映射表中,不然直接返回就Ok了。
下面就是createBean了, we are close。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) {//實例化動做 instanceWrapper = createBeanInstance(beanName, mbd, args); } //.....some codes we don't care. //...... // Initialize the bean instance. Object exposedObject = bean; try {/////裝配動做 populateBean(beanName, mbd, instanceWrapper); if (exposedObject != null) {//後面會講到,暫時不關心 exposedObject = initializeBean(beanName, exposedObject, mbd); } } //........some codes we don't care. return exposedObject; }
比較清晰(一樣去除了一些咱們不關心的代碼),上面的方法分了咱們指望的兩部執行,第一實例化Bean,第二裝配Bean。
第一步實例化主要是經過肯定調用的構造器來最終調用Class.newInstance(args)方法來實例化Bean。不作細究,有興趣能夠本身看看,比較簡單,主要是第二部裝配,也就是處理咱們的@Autowired註解(終於找到正題了)。
方法populateBean執行了最終的Autowired動做,咱們看一下它作了什麼?話說這塊有點麻煩了,開始以前想講幾個比較重要的類和接口吧:
A) PropertyValue:這是一個用來表示Bean屬性的對象,其中定義了屬性的名字和值等信息,如simpleService,和simpleDao屬性。
B) PropertyDescriptor:這個事Bean屬性的描述符,其中定義了該屬性可能存在的setter和getter方法,以及全部Bean的Class對象。
C) InjectionMetadata:這個是注入元數據,包含了目標Bean的Class對象,和注入元素(InjectionElement)集合.
D) InjectionElement:這個是注入元素,包含了注入元素的java.lang.reflect.Member 的對象,以及一個PropertyDescriptor對象。就是對java.lang.reflect.Member的一個封裝,用來執行最終的注入動做,它有兩個子類,分別是:AutowiredFieldElement表示字段屬性,AutowiredMethodElement表示方法。
其實最終的目標就是將PropertyValue中的value值賦給InjectionElement中的Member對象。那它是怎麼作的呢?
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { //嘗試從BeanDefinition中獲取PropertyValue的屬性集合,很明顯沒有值呢還。 PropertyValues pvs = mbd.getPropertyValues(); //.....其中執行了一些BeanPostProcessor的postProcessAfterInstantiation動做,咱們不關心。 //.....移除了 //這裏比較重要,這裏會設置上面的PropertyValues的值,默認狀況下是getResolvedAutowiredMode方法返回 //0, 可是咱們能夠在xml配置文件中設置<beans/>標籤的default-autowire屬性來改變它。 if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE); if (hasInstAwareBpps || needsDepCheck) { PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); if (hasInstAwareBpps) { //這裏即是最最最重要的了,也就是最終的Autowired了。 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; pvs = ibp.postProcessPropertyValues(//瞅到沒,這個方法哦~~~ pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvs == null) { return; } } } } if (needsDepCheck) { checkDependencies(beanName, mbd, filteredPds, pvs); } } applyPropertyValues(beanName, mbd, bw, pvs); }
Spring 嘗試獲取bean definition的PropertyValue集合,開始固然是空的,而後下面即是進行根據名字或者類型爲咱們的PropertyValue集合進行賦值了, 在不設置<beans default-autowire="byName/byType"/>的狀況下是不會調用這個方法的,若是設置了byName,咱們來看看作了什麼?
protected void autowireByName( String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) { //找到還沒賦值的屬性名稱,看下面方法 String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw); for (String propertyName : propertyNames) { if (containsBean(propertyName)) { //遞歸調用getBean,若是沒有建立並註冊,有了直接返回。 Object bean = getBean(propertyName); //將剛獲得或建立的bean賦值給PropertyValue pvs.add(propertyName, bean); //並將該屬性名和實例註冊到依賴關係映射表dependentBeanMap和dependencyForBeanMap中 registerDependentBean(propertyName, beanName); } } } protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) { Set<String> result = new TreeSet<String>(); PropertyValues pvs = mbd.getPropertyValues(); PropertyDescriptor[] pds = bw.getPropertyDescriptors(); //遍歷bean的全部屬性,並將符合條件的屬性名添加到結果列表中 for (PropertyDescriptor pd : pds) { if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) && !BeanUtils.isSimpleProperty(pd.getPropertyType())) { result.add(pd.getName()); } } return StringUtils.toStringArray(result); }
上面兩段代碼的意思是,查看當前bean的全部屬性(描述符),而後依次判斷查找符合條件的屬性,並添加到屬性名稱數組中,而後遍歷這個數組,對其中的屬性名依次調用getBean(propertyName)方法來獲取或建立該名稱的bean實例,並將該bean實例設爲PropertyValue的value值,最後添加到依賴關係映射表中(dependencyForBeanMap和dependentBeanMap)。好了此時PropertyValues有值了,後面就能夠用它來注入到bean的屬性中了。咱們接着看上面populateBean方法。
PropertyValue值設置後,Spring會調用getBeanPostProcessor方法遍歷Bean工廠中註冊的全部BeanPostProcessor,其中就包括AutowiredAnnotationBeanPostProcessor(這些BeanPostProcessor都是系統默認硬編碼註冊到bean工廠中的)。接着就會調用AutowiredAnnotationBeanPostProcessor的postProcessPropertyValues方法,並將以前的PropertyValues和bean實例傳遞進去。
//雖然PropertyValues屬性傳遞過去了,可是並無使用它直接賦值給屬性變量(還不清楚爲何會傳遞它,其實沒用到) @Override public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { //調用下面的方法獲取InjectionMetadata對象(其實InjectionElement集合) InjectionMetadata metadata = findAutowiringMetadata(bean.getClass()); try { metadata.inject(bean, beanName, pvs); } return pvs; } private InjectionMetadata findAutowiringMetadata(Class<?> clazz) { // 先找緩存 InjectionMetadata metadata = this.injectionMetadataCache.get(clazz); if (metadata == null) { synchronized (this.injectionMetadataCache) { metadata = this.injectionMetadataCache.get(clazz); if (metadata == null) { //緩存沒有,調用buildAutowiringMetadata方法構建 metadata = buildAutowiringMetadata(clazz); this.injectionMetadataCache.put(clazz, metadata); } } } return metadata; } private InjectionMetadata buildAutowiringMetadata(Class<?> clazz) { LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<InjectionMetadata.InjectedElement>(); Class<?> targetClass = clazz; do {//這裏一個循環,由於要考慮父類的字段和方法 LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<InjectionMetadata.InjectedElement>(); for (Field field : targetClass.getDeclaredFields()) { //遍歷每個field,找到被標記爲@Autowired的field Annotation annotation = findAutowiredAnnotation(field); if (annotation != null) { if (Modifier.isStatic(field.getModifiers())) { continue;//不可一世static的。 } boolean required = determineRequiredStatus(annotation); //建立AutowiredFieldElement。 currElements.add(new AutowiredFieldElement(field, required)); } } for (Method method : targetClass.getDeclaredMethods()) { //遍歷全部方法,這裏有個橋方法的處理,咱們不關心 Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); Annotation annotation = BridgeMethodResolver .isVisibilityBridgeMethodPair(method, bridgedMethod) ? findAutowiredAnnotation(bridgedMethod) : findAutowiredAnnotation(method); if (annotation != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { continue; } if (method.getParameterTypes().length == 0) { } boolean required = determineRequiredStatus(annotation); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(method); //建立AutowiredMethodElement。 currElements.add(new AutowiredMethodElement(method, required, pd)); } } elements.addAll(0, currElements); targetClass = targetClass.getSuperclass(); } while (targetClass != null && targetClass != Object.class); //將InjectionElement集合添加到新建的InjectionMetadata中。 return new InjectionMetadata(clazz, elements); }
上面三個方法看似複雜其實很簡單,首先Spring嘗試調用findAutowiringMetadata方法獲取該bean的InjectionMetadata實例(也就是有哪些屬性須要被自動裝配,也就是查找被@Autowired註解標記的元素)。怎麼獲取呢?首先去緩存裏面找,找不到就遍歷bean的和父類的字段域和方法,若是別標記爲@Autowired而且不是靜態的就添加到InjectionMetadata中,並添加到緩存中(各類緩存啊)。得到InjectionMetadata對象後便遍歷其中的全部InjectionElement對象,調用其中的inject方法。前面說了InjectionElement有兩個實現類,咱們只看一個就能夠,由於基本相同:
@Override protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable { Field field = (Field) this.member; try { Object value; if (this.cached) { value = resolvedCachedArgument(beanName, this.cachedFieldValue); } else { DependencyDescriptor descriptor = new DependencyDescriptor(field, this.required); Set<String> autowiredBeanNames = new LinkedHashSet<String>(1); TypeConverter typeConverter = beanFactory.getTypeConverter(); //這裏是重中之重,獲取真正的屬性值。 value = beanFactory.resolveDependency(descriptor, beanName, autowiredBeanNames, typeConverter); } if (value != null) { ReflectionUtils.makeAccessible(field); field.set(bean, value);//最終賦值結束。 } } } }
能夠看到,雖然PropertyValues屬性傳遞過去了,可是並無使用它直接賦值給屬性變量(還不清楚爲何會傳遞它,其實沒用到),而是經過調用bean工廠的resolveDependency方法來獲取屬性值得。那咱們看一下resolveDependency作了什麼?
protected Object doResolveDependency(DependencyDescriptor descriptor, Class<?> type, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException { if (type.isArray()) {//若是屬性類型是數組 Class<?> componentType = type.getComponentType(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType, descriptor); if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return converter.convertIfNecessary(matchingBeans.values(), type); }//若是屬性是集合,而且是接口 else if (Collection.class.isAssignableFrom(type) && type.isInterface()) { Class<?> elementType = descriptor.getCollectionType(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType, descriptor); if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter()); return converter.convertIfNecessary(matchingBeans.values(), type); }//若是屬性是Map而且是接口 else if (Map.class.isAssignableFrom(type) && type.isInterface()) { Class<?> keyType = descriptor.getMapKeyType(); Class<?> valueType = descriptor.getMapValueType(); Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType, descriptor); if (autowiredBeanNames != null) { autowiredBeanNames.addAll(matchingBeans.keySet()); } return matchingBeans; }//自定義類型了 else {//都調用了這個方法 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.size() > 1) { String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor); if (autowiredBeanNames != null) { autowiredBeanNames.add(primaryBeanName); } return matchingBeans.get(primaryBeanName); } // We have exactly one match. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next(); if (autowiredBeanNames != null) { autowiredBeanNames.add(entry.getKey()); } return entry.getValue(); } }
這個方法其實就是根據類型到bean工廠中查找類型匹配的bean實例,而後就看到了這幾個條件分支語句,若是是數組,集合,映射表,自定義類型都執行了差很少的操做,findAutowireCandidate方法。這個方法會去工廠中執行類型匹配的查找,將匹配的結果集返回,不一樣的是,集合數組類型會經過TypeConverter進行結果的轉換。
到此爲止,找到了屬性的匹配值,而後反射賦值就完成了整個的自動裝配過程。能夠看出,@Autowired是經過類型來進行自動裝配的。
上面是屬性的賦值過程也就是InjectionFieldElement的inject方法,InjectionMethodElement的inject方法大體相同只是對每個方法參數執行一次resolveDependency方法來獲取參數值,而後反射執行方法。
到此爲止,整個實例化和裝配過程也就講完了,咱們總結一下:
1)一切都是從bean工廠的getBean方法開始的,一旦該方法調用總會返回一個bean實例,不管當前是否存在,不存在就實例化一個並裝配,不然直接返回。
2)實例化和裝配過程當中會屢次遞歸調用getBean方法來解決類之間的依賴。
3)Spring幾乎考慮了全部可能性,因此方法特別複雜但完整有條理。
4)@Autowired最終是根據類型來查找和裝配元素的,可是咱們設置了<beans default-autowire="byName"/>後會影響最終的類型匹配查找。由於在前面有根據BeanDefinition的autowire類型設置PropertyValue值得一步,其中會有新實例的建立和註冊。就是那個autowireByName方法。
咱們上面講完了整個Autowire過程了。那麼,還有一個問題,上一篇咱們知道了何時執行的配置文件讀取和組件掃描,但Spring MVC是在何時開始執行真個實例化過程的呢?很簡單就在組件掃描完成以後,bean工廠的refresh方法中(還記得嗎?)
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { prepareRefresh(); //前面說過,這裏面執行了,組件掃描和配置文件讀取 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); //這裏註冊了BeanPostProcessor,包括AutowiredAnnotationBeanPostProcessor registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); //這裏就執行了全部非延遲加載的實例化工做。//here finishBeanFactoryInitialization(beanFactory); finishRefresh(); } } }
就是上面的finishBeanFactoryInitialization方法執行了裝配工做,該方法會調用bean工廠的preInstantiateSingletons方法,這個方法會遍歷全部註冊的bean definition實例,若是是單例而且是非延遲加載的就調用getBean方法。
好了,到此爲止咱們就清晰的瞭解了,Spring MVC的實例化和自動裝配工做了,若有問題歡迎評論中提出,咱們一塊兒討論。
累死了~~~~~~~