4、IOC容器的依賴注入

一、依賴注入發生的時間

當Spring IoC容器完成了Bean定義資源的定位、載入和解析註冊之後,IoC容器中已經管理類Bean定義的相關數據,可是此時IoC容器尚未對所管理的Bean進行依賴注入,依賴注入在如下兩種狀況發生:java

(1).用戶第一次經過getBean方法向IoC容索要Bean時,IoC容器觸發依賴注入。spring

(2).當用戶在Bean定義資源中爲<Bean>元素配置了lazy-init屬性,即讓容器在解析註冊Bean定義時進行預實例化,觸發依賴注入。編程

BeanFactory接口定義了Spring IoC容器的基本功能規範,是Spring IoC容器所應遵照的最底層和最基本的編程規範。BeanFactory接口中定義了幾個getBean方法,就是用戶向IoC容器索取管理的Bean的方法,咱們經過分析其子類的具體實現,理解Spring IoC容器在用戶索取Bean時如何完成依賴注入。數組

輸入圖片說明

在BeanFactory中咱們看到getBean(String…)函數,它的具體實如今AbstractBeanFactory中緩存

#二、AbstractBeanFactory經過getBean向IoC容器獲取被管理的Bean:安全

AbstractBeanFactory的getBean相關方法的源碼以下:session

//獲取IoC容器中指定名稱的Bean  
   public Object getBean(String name) throws BeansException {  
       //doGetBean纔是真正向IoC容器獲取被管理Bean的過程  
       return doGetBean(name, null, null, false);  
   }  
   //獲取IoC容器中指定名稱和類型的Bean  
   public <T> T getBean(String name, Class<T> requiredType) throws BeansException {  
       //doGetBean纔是真正向IoC容器獲取被管理Bean的過程  
       return doGetBean(name, requiredType, null, false);  
   }  
   //獲取IoC容器中指定名稱和參數的Bean  
   public Object getBean(String name, Object... args) throws BeansException {  
       //doGetBean纔是真正向IoC容器獲取被管理Bean的過程  
       return doGetBean(name, null, args, false);  
   }  
   //獲取IoC容器中指定名稱、類型和參數的Bean  
   public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {  
   //doGetBean纔是真正向IoC容器獲取被管理Bean的過程  
       return doGetBean(name, requiredType, args, false);  
   }  
   //真正實現向IoC容器獲取Bean的功能,也是觸發依賴注入功能的地方  
   @SuppressWarnings("unchecked")  
   protected <T> T doGetBean(  
           final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  
           throws BeansException {  
       //根據指定的名稱獲取被管理Bean的名稱,剝離指定名稱中對容器的相關依賴  
       //若是指定的是別名,將別名轉換爲規範的Bean名稱  
       final String beanName = transformedBeanName(name);  
       Object bean;  
       //先從緩存中取是否已經有被建立過的單態類型的Bean,對於單態模式的Bean整  
       //個IoC容器中只建立一次,不須要重複建立  
       Object sharedInstance = getSingleton(beanName);  
       //IoC容器建立單態模式Bean實例對象  
       if (sharedInstance != null && args == null) {  
           if (logger.isDebugEnabled()) {  
               //若是指定名稱的Bean在容器中已有單態模式的Bean被建立,直接返回  
               //已經建立的Bean  
               if (isSingletonCurrentlyInCreation(beanName)) {  
                   logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +  
                           "' that is not fully initialized yet - a consequence of a circular reference");  
               }  
               else {  
                   logger.debug("Returning cached instance of singleton bean '" + beanName + "'");  
               }  
           }  
           //獲取給定Bean的實例對象,主要是完成FactoryBean的相關處理  
           //注意:BeanFactory是管理容器中Bean的工廠,而FactoryBean是  
           //建立建立對象的工廠Bean,二者之間有區別  
           bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
       }  
       else {//緩存沒有正在建立的單態模式Bean  
           //緩存中已經有已經建立的原型模式Bean,可是因爲循環引用的問題致使實  
           //例化對象失敗  
           if (isPrototypeCurrentlyInCreation(beanName)) {  
               throw new BeanCurrentlyInCreationException(beanName);  
           }  
           //對IoC容器中是否存在指定名稱的BeanDefinition進行檢查,首先檢查是否  
           //能在當前的BeanFactory中獲取的所須要的Bean,若是不能則委託當前容器  
           //的父級容器去查找,若是仍是找不到則沿着容器的繼承體系向父級容器查找  
           BeanFactory parentBeanFactory = getParentBeanFactory();  
           //當前容器的父級容器存在,且當前容器中不存在指定名稱的Bean  
           if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
               //解析指定Bean名稱的原始名稱  
               String nameToLookup = originalBeanName(name);  
               if (args != null) {  
                   //委派父級容器根據指定名稱和顯式的參數查找  
                   return (T) parentBeanFactory.getBean(nameToLookup, args);  
               }  
               else {  
                   //委派父級容器根據指定名稱和類型查找  
                   return parentBeanFactory.getBean(nameToLookup, requiredType);  
               }  
           }  
           //建立的Bean是否須要進行類型驗證,通常不須要  
           if (!typeCheckOnly) {  
               //向容器標記指定的Bean已經被建立  
               markBeanAsCreated(beanName);  
           }  
            //根據指定Bean名稱獲取其父級的Bean定義,主要解決Bean繼承時子類  
           //合併父類公共屬性問題  
           final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
           checkMergedBeanDefinition(mbd, beanName, args);  
           //獲取當前Bean全部依賴Bean的名稱  
           String[] dependsOn = mbd.getDependsOn();  
           //若是當前Bean有依賴Bean  
           if (dependsOn != null) {  
               for (String dependsOnBean : dependsOn) {  
                   //遞歸調用getBean方法,獲取當前Bean的依賴Bean  
                   getBean(dependsOnBean);  
                   //把被依賴Bean註冊給當前依賴的Bean  
                   registerDependentBean(dependsOnBean, beanName);  
               }  
           }  
           //建立單態模式Bean的實例對象  
           if (mbd.isSingleton()) {  
           //這裏使用了一個匿名內部類,建立Bean實例對象,而且註冊給所依賴的對象  
               sharedInstance = getSingleton(beanName, new ObjectFactory() {  
                   public Object getObject() throws BeansException {  
                       try {  
                           //建立一個指定Bean實例對象,若是有父級繼承,則合併子//類和父類的定義  
                           return createBean(beanName, mbd, args);  
                       }  
                       catch (BeansException ex) {  
                           //顯式地從容器單態模式Bean緩存中清除實例對象  
                           destroySingleton(beanName);  
                           throw ex;  
                       }  
                   }  
               });  
               //獲取給定Bean的實例對象  
               bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
           }  
           //IoC容器建立原型模式Bean實例對象  
           else if (mbd.isPrototype()) {  
               //原型模式(Prototype)是每次都會建立一個新的對象  
               Object prototypeInstance = null;  
               try {  
                   //回調beforePrototypeCreation方法,默認的功能是註冊當前創//建的原型對象  
                   beforePrototypeCreation(beanName);  
                   //建立指定Bean對象實例  
                   prototypeInstance = createBean(beanName, mbd, args);  
               }  
               finally {  
                   //回調afterPrototypeCreation方法,默認的功能告訴IoC容器指//定Bean的原型對象再也不建立了  
                   afterPrototypeCreation(beanName);  
               }  
               //獲取給定Bean的實例對象  
               bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
           }  
           //要建立的Bean既不是單態模式,也不是原型模式,則根據Bean定義資源中  
           //配置的生命週期範圍,選擇實例化Bean的合適方法,這種在Web應用程序中  
           //比較經常使用,如:request、session、application等生命週期  
           else {  
               String scopeName = mbd.getScope();  
               final Scope scope = this.scopes.get(scopeName);  
               //Bean定義資源中沒有配置生命週期範圍,則Bean定義不合法  
               if (scope == null) {  
                   throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");  
               }  
               try {  
                   //這裏又使用了一個匿名內部類,獲取一個指定生命週期範圍的實例  
                   Object scopedInstance = scope.get(beanName, new ObjectFactory() {  
                       public Object getObject() throws BeansException {  
                           beforePrototypeCreation(beanName);  
                           try {  
                               return createBean(beanName, mbd, args);  
                           }  
                           finally {  
                               afterPrototypeCreation(beanName);  
                           }  
                       }  
                   });  
                   //獲取給定Bean的實例對象  
                   bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  
               }  
               catch (IllegalStateException ex) {  
                   throw new BeanCreationException(beanName,  
                           "Scope '" + scopeName + "' is not active for the current thread; " +  
                           "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",  
                           ex);  
               }  
           }  
       }  
       //對建立的Bean實例對象進行類型檢查  
       if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {  
           throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  
       }  
       return (T) bean;  
   }

經過上面對向IoC容器獲取Bean方法的分析,咱們能夠看到在Spring中,若是Bean定義的單態模式(Singleton),則容器在建立以前先從緩存中查找,以確保整個容器中只存在一個實例對象。若是Bean定義的是原型模式(Prototype),則容器每次都會建立一個新的實例對象。除此以外,Bean定義還能夠擴展爲指定其生命週期範圍。數據結構

上面的源碼只是定義了根據Bean定義的模式,採起的不一樣建立Bean實例對象的策略,具體的Bean實例對象的建立過程由實現了ObejctFactory接口的匿名內部類的createBean方法完成,ObejctFactory使用委派模式,具體的Bean實例建立過程交由其實現類AbstractAutowireCapableBeanFactory完成,咱們繼續分析AbstractAutowireCapableBeanFactory的createBean方法的源碼,理解其建立Bean實例的具體實現過程。多線程

三、AbstractAutowireCapableBeanFactory建立Bean實例對象:

AbstractAutowireCapableBeanFactory類實現了ObejctFactory接口,建立容器指定的Bean實例對象,同時還對建立的Bean實例對象進行初始化處理。其建立Bean實例對象的方法源碼以下:併發

//建立Bean實例對象  
   protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)  
           throws BeanCreationException {  
       if (logger.isDebugEnabled()) {  
           logger.debug("Creating instance of bean '" + beanName + "'");  
       }  
       //判斷須要建立的Bean是否能夠實例化,便是否能夠經過當前的類加載器加載  
       resolveBeanClass(mbd, beanName);  
       //校驗和準備Bean中的方法覆蓋  
       try {  
           mbd.prepareMethodOverrides();  
       }  
       catch (BeanDefinitionValidationException ex) {  
           throw new BeanDefinitionStoreException(mbd.getResourceDescription(),  
                   beanName, "Validation of method overrides failed", ex);  
       }  
       try {  
           //若是Bean配置了初始化前和初始化後的處理器,則試圖返回一個須要建立//Bean的代理對象  
           Object bean = resolveBeforeInstantiation(beanName, mbd);  
           if (bean != null) {  
               return bean;  
           }  
       }  
       catch (Throwable ex) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
                   "BeanPostProcessor before instantiation of bean failed", ex);  
       }  
       //建立Bean的入口  
       Object beanInstance = doCreateBean(beanName, mbd, args);  
       if (logger.isDebugEnabled()) {  
           logger.debug("Finished creating instance of bean '" + beanName + "'");  
       }  
       return beanInstance;  
   }  
   //真正建立Bean的方法  
   protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
       //封裝被建立的Bean對象  
       BeanWrapper instanceWrapper = null;  
       if (mbd.isSingleton()){//單態模式的Bean,先從容器中緩存中獲取同名Bean  
           instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
       }  
       if (instanceWrapper == null) {  
           //建立實例對象  
           instanceWrapper = createBeanInstance(beanName, mbd, args);  
       }  
       final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  
       //獲取實例化對象的類型  
       Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  
       //調用PostProcessor後置處理器  
       synchronized (mbd.postProcessingLock) {  
           if (!mbd.postProcessed) {  
               applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
               mbd.postProcessed = true;  
           }  
       }  
       // Eagerly cache singletons to be able to resolve circular references  
       //向容器中緩存單態模式的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");  
           }  
           //這裏是一個匿名內部類,爲了防止循環引用,儘早持有對象的引用  
           addSingletonFactory(beanName, new ObjectFactory() {  
               public Object getObject() throws BeansException {  
                   return getEarlyBeanReference(beanName, mbd, bean);  
               }  
           });  
       }  
       //Bean對象的初始化,依賴注入在此觸發  
       //這個exposedObject在初始化完成以後返回做爲依賴注入完成後的Bean  
       Object exposedObject = bean;  
       try {  
           //將Bean實例對象封裝,而且Bean定義中配置的屬性值賦值給實例對象  
           populateBean(beanName, mbd, instanceWrapper);  
           if (exposedObject != null) {  
               //初始化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) {  
           //獲取指定名稱的已註冊的單態模式Bean對象  
           Object earlySingletonReference = getSingleton(beanName, false);  
           if (earlySingletonReference != null) {  
               //根據名稱獲取的以註冊的Bean和正在實例化的Bean是同一個  
               if (exposedObject == bean) {  
                   //當前實例化的Bean初始化完成  
                   exposedObject = earlySingletonReference;  
               }  
               //當前Bean依賴其餘Bean,而且當發生循環引用時不容許新建立實例對象  
               else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
                   String[] dependentBeans = getDependentBeans(beanName);  
                   Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);  
                   //獲取當前Bean所依賴的其餘Bean  
                   for (String dependentBean : dependentBeans) {  
                       //對依賴Bean進行類型檢查  
                       if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
                           actualDependentBeans.add(dependentBean);  
                       }  
                   }  
                   if (!actualDependentBeans.isEmpty()) {  
                       throw new BeanCurrentlyInCreationException(beanName,  
                               "Bean with name '" + beanName + "' has been injected into other beans [" +  
                               StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
                               "] in its raw version as part of a circular reference, but has eventually been " +  
                               "wrapped. This means that said other beans do not use the final version of the " +  
                               "bean. This is often the result of over-eager type matching - consider using " +  
                               "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  
                   }  
               }  
           }  
       }  
       //註冊完成依賴注入的Bean  
       try {  
           registerDisposableBeanIfNecessary(beanName, bean, mbd);  
       }  
       catch (BeanDefinitionValidationException ex) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);  
       }  
       return exposedObject;  
    }

經過對方法源碼的分析,咱們看到具體的依賴注入實如今如下兩個方法中:

(1).createBeanInstance:生成Bean所包含的java對象實例。

(2).populateBean :對Bean屬性的依賴注入進行處理

下面繼續分析這兩個方法的代碼實現。

四、createBeanInstance方法建立Bean的java實例對象:

在createBeanInstance方法中,根據指定的初始化策略,使用靜態工廠、工廠方法或者容器的自動裝配特性生成java實例對象,建立對象的源碼以下:

//建立Bean的實例對象  
   protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {  
       //檢查確認Bean是可實例化的  
       Class beanClass = resolveBeanClass(mbd, beanName);  
       //使用工廠方法對Bean進行實例化  
       if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
                   "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());  
       }  
       if (mbd.getFactoryMethodName() != null)  {  
           //調用工廠方法實例化  
           return instantiateUsingFactoryMethod(beanName, mbd, args);  
       }  
       //使用容器的自動裝配方法進行實例化  
       boolean resolved = false;  
       boolean autowireNecessary = false;  
       if (args == null) {  
           synchronized (mbd.constructorArgumentLock) {  
               if (mbd.resolvedConstructorOrFactoryMethod != null) {  
                   resolved = true;  
                   autowireNecessary = mbd.constructorArgumentsResolved;  
               }  
           }  
       }  
       if (resolved) {  
           if (autowireNecessary) {  
               //配置了自動裝配屬性,使用容器的自動裝配實例化  
               //容器的自動裝配是根據參數類型匹配Bean的構造方法  
               return autowireConstructor(beanName, mbd, null, null);  
           }  
           else {  
               //使用默認的無參構造方法實例化  
               return instantiateBean(beanName, mbd);  
           }  
       }  
       //使用Bean的構造方法進行實例化  
       Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  
       if (ctors != null ||  
               mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||  
               mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {  
           //使用容器的自動裝配特性,調用匹配的構造方法實例化  
           return autowireConstructor(beanName, mbd, ctors, args);  
       }  
       //使用默認的無參構造方法實例化  
       return instantiateBean(beanName, mbd);  
   }   
   //使用默認的無參構造方法實例化Bean對象  
   protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {  
       try {  
           Object beanInstance;  
           final BeanFactory parent = this;  
           //獲取系統的安全管理接口,JDK標準的安全管理API  
           if (System.getSecurityManager() != null) {  
               //這裏是一個匿名內置類,根據實例化策略建立實例對象  
               beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {  
                   public Object run() {  
                       return getInstantiationStrategy().instantiate(mbd, beanName, parent);  
                   }  
               }, getAccessControlContext());  
           }  
           else {  
               //將實例化的對象封裝起來  
               beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);  
           }  
           BeanWrapper bw = new BeanWrapperImpl(beanInstance);  
           initBeanWrapper(bw);  
           return bw;  
       }  
       catch (Throwable ex) {  
           throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
       }  
   }

通過對上面的代碼分析,咱們能夠看出,對使用工廠方法和自動裝配特性的Bean的實例化至關比較清楚,調用相應的工廠方法或者參數匹配的構造方法便可完成實例化對象的工做,可是對於咱們最常使用的默認無參構造方法就須要使用相應的初始化策略(JDK的反射機制或者CGLIB)來進行初始化了,在方法getInstantiationStrategy().instantiate中就具體實現類使用初始策略實例化對象。

五、SimpleInstantiationStrategy類使用默認的無參構造方法建立Bean實例化對象:

在使用默認的無參構造方法建立Bean的實例化對象時,方法getInstantiationStrategy().instantiate調用了SimpleInstantiationStrategy類中的實例化Bean的方法,其源碼以下:

//使用初始化策略實例化Bean對象  
   public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {  
       //若是Bean定義中沒有方法覆蓋,則就不須要CGLIB父類類的方法  
       if (beanDefinition.getMethodOverrides().isEmpty()) {  
           Constructor<?> constructorToUse;  
           synchronized (beanDefinition.constructorArgumentLock) {  
               //獲取對象的構造方法或工廠方法  
               constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;  
               //若是沒有構造方法且沒有工廠方法  
               if (constructorToUse == null) {  
                   //使用JDK的反射機制,判斷要實例化的Bean是不是接口  
                   final Class clazz = beanDefinition.getBeanClass();  
                   if (clazz.isInterface()) {  
                       throw new BeanInstantiationException(clazz, "Specified class is an interface");  
                   }  
                   try {  
                       if (System.getSecurityManager() != null) {  
                       //這裏是一個匿名內置類,使用反射機制獲取Bean的構造方法  
                           constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {  
                               public Constructor run() throws Exception {  
                                   return clazz.getDeclaredConstructor((Class[]) null);  
                               }  
                           });  
                       }  
                       else {  
                           constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);  
                       }  
                       beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;  
                   }  
                   catch (Exception ex) {  
                       throw new BeanInstantiationException(clazz, "No default constructor found", ex);  
                   }  
               }  
           }  
           //使用BeanUtils實例化,經過反射機制調用」構造方法.newInstance(arg)」來進行實例化  
           return BeanUtils.instantiateClass(constructorToUse);  
       }  
       else {  
           //使用CGLIB來實例化對象  
           return instantiateWithMethodInjection(beanDefinition, beanName, owner);  
       }  
    }

經過上面的代碼分析,咱們看到了若是Bean有方法被覆蓋了,則使用JDK的反射機制進行實例化,不然,使用CGLIB進行實例化。

instantiateWithMethodInjection方法調用SimpleInstantiationStrategy的子類CglibSubclassingInstantiationStrategy使用CGLIB來進行初始化,其源碼以下:

//使用CGLIB進行Bean對象實例化  
   public Object instantiate(Constructor ctor, Object[] args) {  
           //CGLIB中的類  
           Enhancer enhancer = new Enhancer();  
           //將Bean自己做爲其基類  
           enhancer.setSuperclass(this.beanDefinition.getBeanClass());  
           enhancer.setCallbackFilter(new CallbackFilterImpl());  
           enhancer.setCallbacks(new Callback[] {  
                   NoOp.INSTANCE,  
                   new LookupOverrideMethodInterceptor(),  
                   new ReplaceOverrideMethodInterceptor()  
           });  
           //使用CGLIB的create方法生成實例對象  
           return (ctor == null) ?   
                   enhancer.create() :   
                   enhancer.create(ctor.getParameterTypes(), args);  
       }

CGLIB是一個經常使用的字節碼生成器的類庫,它提供了一系列API實現java字節碼的生成和轉換功能。咱們在學習JDK的動態代理時都知道,JDK的動態代理只能針對接口,若是一個類沒有實現任何接口,要對其進行動態代理只能使用CGLIB。

六、populateBean方法對Bean屬性的依賴注入:

在第3步的分析中咱們已經瞭解到Bean的依賴注入分爲如下兩個過程:

(1).createBeanInstance:生成Bean所包含的java對象實例。

(2).populateBean :對Bean屬性的依賴注入進行處理。

第四、5步中咱們已經分析了容器初始化生成Bean所包含的Java實例對象的過程,如今咱們繼續分析生成對象後,Spring IoC容器是如何將Bean的屬性依賴關係注入Bean實例對象中並設置好的,屬性依賴注入的代碼以下:

//將Bean屬性設置到生成的實例對象上  
   protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {  
       //獲取容器在解析Bean定義資源時爲BeanDefiniton中設置的屬性值  
       PropertyValues pvs = mbd.getPropertyValues();  
       //實例對象爲null  
       if (bw == null) {  
           //屬性值不爲空  
           if (!pvs.isEmpty()) {  
               throw new BeanCreationException(  
                       mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");  
           }  
           else {  
               //實例對象爲null,屬性值也爲空,不須要設置屬性值,直接返回  
               return;  
           }  
       }  
       //在設置屬性以前調用Bean的PostProcessor後置處理器  
       boolean continueWithPropertyPopulation = true;  
       if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
           for (BeanPostProcessor bp : getBeanPostProcessors()) {  
               if (bp instanceof InstantiationAwareBeanPostProcessor) {  
                   InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
                   if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  
                       continueWithPropertyPopulation = false;  
                       break;  
                   }  
               }  
           }  
       }  
       if (!continueWithPropertyPopulation) {  
           return;  
       }  
       //依賴注入開始,首先處理autowire自動裝配的注入  
       if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  
               mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
           MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
           //對autowire自動裝配的處理,根據Bean名稱自動裝配注入  
           if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
               autowireByName(beanName, mbd, bw, newPvs);  
           }  
           //根據Bean類型自動裝配注入  
           if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
               autowireByType(beanName, mbd, bw, newPvs);  
           }  
           pvs = newPvs;  
       }  
       //檢查容器是否持有用於處理單態模式Bean關閉時的後置處理器  
       boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();  
       //Bean實例對象沒有依賴,即沒有繼承基類  
       boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);  
       if (hasInstAwareBpps || needsDepCheck) {  
           //從實例對象中提取屬性描述符  
           PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);  
           if (hasInstAwareBpps) {  
               for (BeanPostProcessor bp : getBeanPostProcessors()) {  
                   if (bp instanceof InstantiationAwareBeanPostProcessor) {  
                       InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
                       //使用BeanPostProcessor處理器處理屬性值  
                       pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);  
                       if (pvs == null) {  
                           return;  
                       }  
                   }  
               }  
           }  
           if (needsDepCheck) {  
               //爲要設置的屬性進行依賴檢查  
               checkDependencies(beanName, mbd, filteredPds, pvs);  
           }  
       }  
       //對屬性進行注入  
       applyPropertyValues(beanName, mbd, bw, pvs);  
   }  
   //解析並注入依賴屬性的過程  
   protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {  
       if (pvs == null || pvs.isEmpty()) {  
           return;  
       }  
       //封裝屬性值  
       MutablePropertyValues mpvs = null;  
       List<PropertyValue> original;  
       if (System.getSecurityManager()!= null) {  
           if (bw instanceof BeanWrapperImpl) {  
               //設置安全上下文,JDK安全機制  
               ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());  
           }  
       }  
       if (pvs instanceof MutablePropertyValues) {  
           mpvs = (MutablePropertyValues) pvs;  
           //屬性值已經轉換  
           if (mpvs.isConverted()) {  
               try {  
                   //爲實例化對象設置屬性值  
                   bw.setPropertyValues(mpvs);  
                   return;  
               }  
               catch (BeansException ex) {  
                   throw new BeanCreationException(  
                           mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
               }  
           }  
           //獲取屬性值對象的原始類型值  
           original = mpvs.getPropertyValueList();  
       }  
       else {  
           original = Arrays.asList(pvs.getPropertyValues());  
       }  
       //獲取用戶自定義的類型轉換  
       TypeConverter converter = getCustomTypeConverter();  
       if (converter == null) {  
           converter = bw;  
       }  
       //建立一個Bean定義屬性值解析器,將Bean定義中的屬性值解析爲Bean實例對象  
       //的實際值  
       BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);  
       //爲屬性的解析值建立一個拷貝,將拷貝的數據注入到實例對象中  
       List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());  
       boolean resolveNecessary = false;  
       for (PropertyValue pv : original) {  
           //屬性值不須要轉換  
           if (pv.isConverted()) {  
               deepCopy.add(pv);  
           }  
           //屬性值須要轉換  
           else {  
               String propertyName = pv.getName();  
               //原始的屬性值,即轉換以前的屬性值  
               Object originalValue = pv.getValue();  
               //轉換屬性值,例如將引用轉換爲IoC容器中實例化對象引用  
               Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);  
               //轉換以後的屬性值  
               Object convertedValue = resolvedValue;  
               //屬性值是否能夠轉換  
               boolean convertible = bw.isWritableProperty(propertyName) &&  
                       !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);  
               if (convertible) {  
                   //使用用戶自定義的類型轉換器轉換屬性值  
                   convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);  
               }  
               //存儲轉換後的屬性值,避免每次屬性注入時的轉換工做  
               if (resolvedValue == originalValue) {  
                   if (convertible) {  
                       //設置屬性轉換以後的值  
                       pv.setConvertedValue(convertedValue);  
                   }  
                   deepCopy.add(pv);  
               }  
               //屬性是可轉換的,且屬性原始值是字符串類型,且屬性的原始類型值不是  
               //動態生成的字符串,且屬性的原始值不是集合或者數組類型  
               else if (convertible && originalValue instanceof TypedStringValue &&  
                       !((TypedStringValue) originalValue).isDynamic() &&  
                       !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {  
                   pv.setConvertedValue(convertedValue);  
                   deepCopy.add(pv);  
               }  
               else {  
                   resolveNecessary = true;  
                   //從新封裝屬性的值  
                   deepCopy.add(new PropertyValue(pv, convertedValue));  
               }  
           }  
       }  
       if (mpvs != null && !resolveNecessary) {  
           //標記屬性值已經轉換過  
           mpvs.setConverted();  
       }  
       //進行屬性依賴注入  
       try {  
           bw.setPropertyValues(new MutablePropertyValues(deepCopy));  
       }  
       catch (BeansException ex) {  
           throw new BeanCreationException(  
                   mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
       }  
    }

分析上述代碼,咱們能夠看出,對屬性的注入過程分如下兩種狀況:

(1).屬性值類型不須要轉換時,不須要解析屬性值,直接準備進行依賴注入。

(2).屬性值須要進行類型轉換時,如對其餘對象的引用等,首先須要解析屬性值,而後對解析後的屬性值進行依賴注入。

對屬性值的解析是在BeanDefinitionValueResolver類中的resolveValueIfNecessary方法中進行的,對屬性值的依賴注入是經過bw.setPropertyValues方法實現的,在分析屬性值的依賴注入以前,咱們先分析一下對屬性值的解析過程。

七、BeanDefinitionValueResolver解析屬性值:

當容器在對屬性進行依賴注入時,若是發現屬性值須要進行類型轉換,如屬性值是容器中另外一個Bean實例對象的引用,則容器首先須要根據屬性值解析出所引用的對象,而後才能將該引用對象注入到目標實例對象的屬性上去,對屬性進行解析的由resolveValueIfNecessary方法實現,其源碼以下:

//解析屬性值,對注入類型進行轉換  
   public Object resolveValueIfNecessary(Object argName, Object value) {  
       //對引用類型的屬性進行解析  
       if (value instanceof RuntimeBeanReference) {  
           RuntimeBeanReference ref = (RuntimeBeanReference) value;  
           //調用引用類型屬性的解析方法  
           return resolveReference(argName, ref);  
       }  
       //對屬性值是引用容器中另外一個Bean名稱的解析  
       else if (value instanceof RuntimeBeanNameReference) {  
           String refName = ((RuntimeBeanNameReference) value).getBeanName();  
           refName = String.valueOf(evaluate(refName));  
           //從容器中獲取指定名稱的Bean  
           if (!this.beanFactory.containsBean(refName)) {  
               throw new BeanDefinitionStoreException(  
                       "Invalid bean name '" + refName + "' in bean reference for " + argName);  
           }  
           return refName;  
       }  
       //對Bean類型屬性的解析,主要是Bean中的內部類  
       else if (value instanceof BeanDefinitionHolder) {  
           BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;  
           return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());  
       }  
       else if (value instanceof BeanDefinition) {  
           BeanDefinition bd = (BeanDefinition) value;  
           return resolveInnerBean(argName, "(inner bean)", bd);  
       }  
       //對集合數組類型的屬性解析  
       else if (value instanceof ManagedArray) {  
           ManagedArray array = (ManagedArray) value;  
           //獲取數組的類型  
           Class elementType = array.resolvedElementType;  
           if (elementType == null) {  
               //獲取數組元素的類型  
               String elementTypeName = array.getElementTypeName();  
               if (StringUtils.hasText(elementTypeName)) {  
                   try {  
                       //使用反射機制建立指定類型的對象  
                       elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());  
                       array.resolvedElementType = elementType;  
                   }  
                   catch (Throwable ex) {  
                       throw new BeanCreationException(  
                               this.beanDefinition.getResourceDescription(), this.beanName,  
                               "Error resolving array type for " + argName, ex);  
                   }  
               }  
               //沒有獲取到數組的類型,也沒有獲取到數組元素的類型,則直接設置數  
               //組的類型爲Object  
               else {  
                   elementType = Object.class;  
               }  
           }  
           //建立指定類型的數組  
           return resolveManagedArray(argName, (List<?>) value, elementType);  
       }  
       //解析list類型的屬性值  
       else if (value instanceof ManagedList) {  
           return resolveManagedList(argName, (List<?>) value);  
       }  
       //解析set類型的屬性值  
       else if (value instanceof ManagedSet) {  
           return resolveManagedSet(argName, (Set<?>) value);  
       }  
       //解析map類型的屬性值  
       else if (value instanceof ManagedMap) {  
           return resolveManagedMap(argName, (Map<?, ?>) value);  
       }  
       //解析props類型的屬性值,props其實就是key和value均爲字符串的map  
       else if (value instanceof ManagedProperties) {  
           Properties original = (Properties) value;  
           //建立一個拷貝,用於做爲解析後的返回值  
           Properties copy = new Properties();  
           for (Map.Entry propEntry : original.entrySet()) {  
               Object propKey = propEntry.getKey();  
               Object propValue = propEntry.getValue();  
               if (propKey instanceof TypedStringValue) {  
                   propKey = evaluate((TypedStringValue) propKey);  
               }  
               if (propValue instanceof TypedStringValue) {  
                   propValue = evaluate((TypedStringValue) propValue);  
               }  
               copy.put(propKey, propValue);  
           }  
           return copy;  
       }  
       //解析字符串類型的屬性值  
       else if (value instanceof TypedStringValue) {  
           TypedStringValue typedStringValue = (TypedStringValue) value;  
           Object valueObject = evaluate(typedStringValue);  
           try {  
               //獲取屬性的目標類型  
               Class<?> resolvedTargetType = resolveTargetType(typedStringValue);  
               if (resolvedTargetType != null) {  
                   //對目標類型的屬性進行解析,遞歸調用  
                   return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);  
               }  
               //沒有獲取到屬性的目標對象,則按Object類型返回  
               else {  
                   return valueObject;  
               }  
           }  
           catch (Throwable ex) {  
               throw new BeanCreationException(  
                       this.beanDefinition.getResourceDescription(), this.beanName,  
                       "Error converting typed String value for " + argName, ex);  
           }  
       }  
       else {  
           return evaluate(value);  
       }  
   }  
   //解析引用類型的屬性值  
   private Object resolveReference(Object argName, RuntimeBeanReference ref) {  
       try {  
           //獲取引用的Bean名稱  
           String refName = ref.getBeanName();  
           refName = String.valueOf(evaluate(refName));  
           //若是引用的對象在父類容器中,則從父類容器中獲取指定的引用對象  
           if (ref.isToParent()) {  
               if (this.beanFactory.getParentBeanFactory() == null) {  
                   throw new BeanCreationException(  
                           this.beanDefinition.getResourceDescription(), this.beanName,  
                           "Can't resolve reference to bean '" + refName +  
                           "' in parent factory: no parent factory available");  
               }  
               return this.beanFactory.getParentBeanFactory().getBean(refName);  
           }  
           //從當前的容器中獲取指定的引用Bean對象,若是指定的Bean沒有被實例化  
           //則會遞歸觸發引用Bean的初始化和依賴注入  
           else {  
               Object bean = this.beanFactory.getBean(refName);  
               //將當前實例化對象的依賴引用對象  
               this.beanFactory.registerDependentBean(refName, this.beanName);  
               return bean;  
           }  
       }  
       catch (BeansException ex) {  
           throw new BeanCreationException(  
                   this.beanDefinition.getResourceDescription(), this.beanName,  
                   "Cannot resolve reference to bean '" + ref.getBeanName() + "' while setting " + argName, ex);  
       }  
   }   
   //解析array類型的屬性  
   private Object resolveManagedArray(Object argName, List<?> ml, Class elementType) {  
       //建立一個指定類型的數組,用於存放和返回解析後的數組  
       Object resolved = Array.newInstance(elementType, ml.size());  
       for (int i = 0; i < ml.size(); i++) {  
       //遞歸解析array的每個元素,並將解析後的值設置到resolved數組中,索引爲i  
           Array.set(resolved, i,  
               resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));  
       }  
       return resolved;  
   }  
   //解析list類型的屬性  
   private List resolveManagedList(Object argName, List<?> ml) {  
       List<Object> resolved = new ArrayList<Object>(ml.size());  
       for (int i = 0; i < ml.size(); i++) {  
           //遞歸解析list的每個元素  
           resolved.add(  
               resolveValueIfNecessary(new KeyedArgName(argName, i), ml.get(i)));  
       }  
       return resolved;  
   }  
   //解析set類型的屬性  
   private Set resolveManagedSet(Object argName, Set<?> ms) {  
       Set<Object> resolved = new LinkedHashSet<Object>(ms.size());  
       int i = 0;  
       //遞歸解析set的每個元素  
       for (Object m : ms) {  
           resolved.add(resolveValueIfNecessary(new KeyedArgName(argName, i), m));  
           i++;  
       }  
       return resolved;  
   }  
   //解析map類型的屬性  
   private Map resolveManagedMap(Object argName, Map<?, ?> mm) {  
       Map<Object, Object> resolved = new LinkedHashMap<Object, Object>(mm.size());  
       //遞歸解析map中每個元素的key和value  
       for (Map.Entry entry : mm.entrySet()) {  
           Object resolvedKey = resolveValueIfNecessary(argName, entry.getKey());  
           Object resolvedValue = resolveValueIfNecessary(  
                   new KeyedArgName(argName, entry.getKey()), entry.getValue());  
           resolved.put(resolvedKey, resolvedValue);  
       }  
       return resolved;  
   }

經過上面的代碼分析,咱們明白了Spring是如何將引用類型,內部類以及集合類型等屬性進行解析的,屬性值解析完成後就能夠進行依賴注入了,依賴注入的過程就是Bean對象實例設置到它所依賴的Bean對象屬性上去,在第7步中咱們已經說過,依賴注入是經過bw.setPropertyValues方法實現的,該方法也使用了委託模式,在BeanWrapper接口中至少定義了方法聲明,依賴注入的具體實現交由其實現類BeanWrapperImpl來完成,下面咱們就分析依BeanWrapperImpl中賴注入相關的源碼。

八、BeanWrapperImpl對Bean屬性的依賴注入:

BeanWrapperImpl類主要是對容器中完成初始化的Bean實例對象進行屬性的依賴注入,即把Bean對象設置到它所依賴的另外一個Bean的屬性中去,依賴注入的相關源碼以下:

//實現屬性依賴注入功能  
   private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {  
       //PropertyTokenHolder主要保存屬性的名稱、路徑,以及集合的size等信息  
       String propertyName = tokens.canonicalName;  
       String actualName = tokens.actualName;  
       //keys是用來保存集合類型屬性的size  
       if (tokens.keys != null) {  
           //將屬性信息拷貝  
           PropertyTokenHolder getterTokens = new PropertyTokenHolder();  
           getterTokens.canonicalName = tokens.canonicalName;  
           getterTokens.actualName = tokens.actualName;  
           getterTokens.keys = new String[tokens.keys.length - 1];  
           System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);  
           Object propValue;  
           try {  
               //獲取屬性值,該方法內部使用JDK的內省( Introspector)機制,調用屬性//的getter(readerMethod)方法,獲取屬性的值  
               propValue = getPropertyValue(getterTokens);  
           }  
           catch (NotReadablePropertyException ex) {  
               throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,  
                       "Cannot access indexed value in property referenced " +  
                       "in indexed property path '" + propertyName + "'", ex);  
           }  
           //獲取集合類型屬性的長度  
           String key = tokens.keys[tokens.keys.length - 1];  
           if (propValue == null) {  
               throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,  
                       "Cannot access indexed value in property referenced " +  
                       "in indexed property path '" + propertyName + "': returned null");  
           }  
           //注入array類型的屬性值  
           else if (propValue.getClass().isArray()) {  
               //獲取屬性的描述符  
               PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
               //獲取數組的類型  
               Class requiredType = propValue.getClass().getComponentType();  
               //獲取數組的長度  
               int arrayIndex = Integer.parseInt(key);  
               Object oldValue = null;  
               try {  
                   //獲取數組之前初始化的值  
                   if (isExtractOldValueForEditor()) {  
                       oldValue = Array.get(propValue, arrayIndex);  
                   }  
                   //將屬性的值賦值給數組中的元素  
                   Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,  
                           new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));  
                   Array.set(propValue, arrayIndex, convertedValue);  
               }  
               catch (IndexOutOfBoundsException ex) {  
                   throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,  
                           "Invalid array index in property path '" + propertyName + "'", ex);  
               }  
           }  
           //注入list類型的屬性值  
           else if (propValue instanceof List) {  
               PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
               //獲取list集合的類型  
               Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(  
                       pd.getReadMethod(), tokens.keys.length);  
               List list = (List) propValue;  
               //獲取list集合的size  
               int index = Integer.parseInt(key);  
               Object oldValue = null;  
               if (isExtractOldValueForEditor() && index < list.size()) {  
                   oldValue = list.get(index);  
               }  
               //獲取list解析後的屬性值  
               Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,  
                       new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));  
               if (index < list.size()) {  
                   //爲list屬性賦值  
                   list.set(index, convertedValue);  
               }  
               //若是list的長度大於屬性值的長度,則多餘的元素賦值爲null  
               else if (index >= list.size()) {  
                   for (int i = list.size(); i < index; i++) {  
                       try {  
                           list.add(null);  
                       }  
                       catch (NullPointerException ex) {  
                           throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,  
                                   "Cannot set element with index " + index + " in List of size " +  
                                   list.size() + ", accessed using property path '" + propertyName +  
                                   "': List does not support filling up gaps with null elements");  
                       }  
                   }  
                   list.add(convertedValue);  
               }  
           }  
           //注入map類型的屬性值  
           else if (propValue instanceof Map) {  
               PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
               //獲取map集合key的類型  
               Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(  
                       pd.getReadMethod(), tokens.keys.length);  
               //獲取map集合value的類型  
               Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(  
                       pd.getReadMethod(), tokens.keys.length);  
               Map map = (Map) propValue;  
               //解析map類型屬性key值  
               Object convertedMapKey = convertIfNecessary(null, null, key, mapKeyType,  
                       new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));  
               Object oldValue = null;  
               if (isExtractOldValueForEditor()) {  
                   oldValue = map.get(convertedMapKey);  
               }  
               //解析map類型屬性value值  
               Object convertedMapValue = convertIfNecessary(  
                       propertyName, oldValue, pv.getValue(), mapValueType,  
                       new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1)));  
               //將解析後的key和value值賦值給map集合屬性  
               map.put(convertedMapKey, convertedMapValue);  
           }  
           else {  
               throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,  
                       "Property referenced in indexed property path '" + propertyName +  
                       "' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]");  
           }  
       }  
       //對非集合類型的屬性注入  
       else {  
           PropertyDescriptor pd = pv.resolvedDescriptor;  
           if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {  
               pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
               //沒法獲取到屬性名或者屬性沒有提供setter(寫方法)方法  
               if (pd == null || pd.getWriteMethod() == null) {  
                   //若是屬性值是可選的,即不是必須的,則忽略該屬性值  
                   if (pv.isOptional()) {  
                       logger.debug("Ignoring optional value for property '" + actualName +  
                               "' - property not found on bean class [" + getRootClass().getName() + "]");  
                       return;  
                   }  
                   //若是屬性值是必須的,則拋出沒法給屬性賦值,由於天天提供setter方法異常  
                   else {  
                       PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());  
                       throw new NotWritablePropertyException(  
                               getRootClass(), this.nestedPath + propertyName,  
                               matches.buildErrorMessage(), matches.getPossibleMatches());  
                   }  
               }  
               pv.getOriginalPropertyValue().resolvedDescriptor = pd;  
           }  
           Object oldValue = null;  
           try {  
               Object originalValue = pv.getValue();  
               Object valueToApply = originalValue;  
               if (!Boolean.FALSE.equals(pv.conversionNecessary)) {  
                   if (pv.isConverted()) {  
                       valueToApply = pv.getConvertedValue();  
                   }  
                   else {  
                       if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {  
                           //獲取屬性的getter方法(讀方法),JDK內省機制  
                           final Method readMethod = pd.getReadMethod();  
                           //若是屬性的getter方法不是public訪問控制權限的,即訪問控制權限比較嚴格,  
                           //則使用JDK的反射機制強行訪問非public的方法(暴力讀取屬性值)  
                           if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&  
                                   !readMethod.isAccessible()) {  
                               if (System.getSecurityManager()!= null) {  
                                   //匿名內部類,根據權限修改屬性的讀取控制限制  
                                   AccessController.doPrivileged(new PrivilegedAction<Object>() {  
                                       public Object run() {  
                                           readMethod.setAccessible(true);  
                                           return null;  
                                       }  
                                   });  
                               }  
                               else {  
                                   readMethod.setAccessible(true);  
                               }  
                           }  
                           try {  
                               //屬性沒有提供getter方法時,調用潛在的讀取屬性值//的方法,獲取屬性值  
                               if (System.getSecurityManager() != null) {  
                                   oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
                                       public Object run() throws Exception {  
                                           return readMethod.invoke(object);  
                                       }  
                                   }, acc);  
                               }  
                               else {  
                                   oldValue = readMethod.invoke(object);  
                               }  
                           }  
                           catch (Exception ex) {  
                               if (ex instanceof PrivilegedActionException) {  
                                   ex = ((PrivilegedActionException) ex).getException();  
                               }  
                               if (logger.isDebugEnabled()) {  
                                   logger.debug("Could not read previous value of property '" +  
                                           this.nestedPath + propertyName + "'", ex);  
                               }  
                           }  
                       }  
                       //設置屬性的注入值  
                       valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);  
                   }  
                   pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);  
               }  
               //根據JDK的內省機制,獲取屬性的setter(寫方法)方法  
               final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?  
                       ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :  
                       pd.getWriteMethod());  
               //若是屬性的setter方法是非public,即訪問控制權限比較嚴格,則使用JDK的反射機制,  
               //強行設置setter方法可訪問(暴力爲屬性賦值)  
               if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {  
                   //若是使用了JDK的安全機制,則須要權限驗證  
                   if (System.getSecurityManager()!= null) {  
                       AccessController.doPrivileged(new PrivilegedAction<Object>() {  
                           public Object run() {  
                               writeMethod.setAccessible(true);  
                               return null;  
                           }  
                       });  
                   }  
                   else {  
                       writeMethod.setAccessible(true);  
                   }  
               }  
               final Object value = valueToApply;  
               if (System.getSecurityManager() != null) {  
                   try {  
                       //將屬性值設置到屬性上去  
                       AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
                           public Object run() throws Exception {  
                               writeMethod.invoke(object, value);  
                               return null;  
                           }  
                       }, acc);  
                   }  
                   catch (PrivilegedActionException ex) {  
                       throw ex.getException();  
                   }  
               }  
               else {  
                   writeMethod.invoke(this.object, value);  
               }  
           }  
           catch (TypeMismatchException ex) {  
               throw ex;  
           }  
           catch (InvocationTargetException ex) {  
               PropertyChangeEvent propertyChangeEvent =  
                       new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());  
               if (ex.getTargetException() instanceof ClassCastException) {  
                   throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());  
               }  
               else {  
                   throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());  
               }  
           }  
           catch (Exception ex) {  
               PropertyChangeEvent pce =  
                       new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());  
               throw new MethodInvocationException(pce, ex);  
           }  
       }  
    }

經過對上面注入依賴代碼的分析,咱們已經明白了Spring IoC容器是如何將屬性的值注入到Bean實例對象中去的:

(1).對於集合類型的屬性,將其屬性值解析爲目標類型的集合後直接賦值給屬性。

(2).對於非集合類型的屬性,大量使用了JDK的反射和內省機制,經過屬性的getter方法(reader method)獲取指定屬性注入之前的值,同時調用屬性的setter方法(writer method)爲屬性設置注入後的值。看到這裏相信不少人都明白了Spring的setter注入原理。

至此Spring IoC容器對Bean定義資源文件的定位,載入、解析和依賴注入已經所有分析完畢,如今Spring IoC容器中管理了一系列靠依賴關係聯繫起來的Bean,程序不須要應用本身手動建立所需的對象,Spring IoC容器會在咱們使用的時候自動爲咱們建立,而且爲咱們注入好相關的依賴,這就是Spring核心功能的控制反轉和依賴注入的相關功能。

5、IoC容器的高級特性

一、介紹

經過前面4篇文章對Spring IoC容器的源碼分析,咱們已經基本上了解了Spring IoC容器對Bean定義資源的定位、讀入和解析過程,同時也清楚了當用戶經過getBean方法向IoC容器獲取被管理的Bean時,IoC容器對Bean進行的初始化和依賴注入過程,這些是Spring IoC容器的基本功能特性。Spring IoC容器還有一些高級特性,如使用lazy-init屬性對Bean預初始化、FactoryBean產生或者修飾Bean對象的生成、IoC容器初始化Bean過程當中使用BeanPostProcessor後置處理器對Bean聲明週期事件管理和IoC容器的autowiring自動裝配功能等。

二、Spring IoC容器的lazy-init屬性實現預實例化:

經過前面咱們對IoC容器的實現和工做原理分析,咱們知道IoC容器的初始化過程就是對Bean定義資源的定位、載入和註冊,此時容器對Bean的依賴注入並無發生,依賴注入主要是在應用程序第一次向容器索取Bean時,經過getBean方法的調用完成。

當Bean定義資源的<Bean>元素中配置了lazy-init屬性時,容器將會在初始化的時候對所配置的Bean進行預實例化,Bean的依賴注入在容器初始化的時候就已經完成。這樣,當應用程序第一次向容器索取被管理的Bean時,就不用再初始化和對Bean進行依賴注入了,直接從容器中獲取已經完成依賴注入的現成Bean,能夠提升應用第一次向容器獲取Bean的性能

下面咱們經過代碼分析容器預實例化的實現過程:

(1).refresh()

先從IoC容器的初始會過程開始,經過前面文章分析,咱們知道IoC容器讀入已經定位的Bean定義資源是從refresh方法開始的,咱們首先從AbstractApplicationContext類的refresh方法入手分析,源碼以下:

//容器初始化的過程,讀入Bean定義資源,並解析註冊  
   public void refresh() throws BeansException, IllegalStateException {  
       synchronized (this.startupShutdownMonitor) {  
            //調用容器準備刷新的方法,獲取容器的當時時間,同時給容器設置同步標識  
            prepareRefresh();  
            //告訴子類啓動refreshBeanFactory()方法,Bean定義資源文件的載入從  
            //子類的refreshBeanFactory()方法啓動  
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
            //爲BeanFactory配置容器特性,例如類加載器、事件處理器等  
           prepareBeanFactory(beanFactory);  
           try {  
               //爲容器的某些子類指定特殊的BeanPost事件處理器  
               postProcessBeanFactory(beanFactory);  
               //調用全部註冊的BeanFactoryPostProcessor的Bean  
               invokeBeanFactoryPostProcessors(beanFactory);  
               //爲BeanFactory註冊BeanPost事件處理器.  
               //BeanPostProcessor是Bean後置處理器,用於監聽容器觸發的事件  
               registerBeanPostProcessors(beanFactory);  
               //初始化信息源,和國際化相關.  
               initMessageSource();  
               //初始化容器事件傳播器.  
               initApplicationEventMulticaster();  
               //調用子類的某些特殊Bean初始化方法  
               onRefresh();  
               //爲事件傳播器註冊事件監聽器.  
               registerListeners();  
               //這裏是對容器lazy-init屬性進行處理的入口方法  
               finishBeanFactoryInitialization(beanFactory);  
               //初始化容器的生命週期事件處理器,併發布容器的生命週期事件  
               finishRefresh();  
           }  
           catch (BeansException ex) {  
               //銷燬以建立的單態Bean  
               destroyBeans();  
               //取消refresh操做,重置容器的同步標識.  
               cancelRefresh(ex);  
               throw ex;  
           }  
       }  
    }

在refresh方法中ConfigurableListableBeanFactorybeanFactory = obtainFreshBeanFactory();啓動了Bean定義資源的載入、註冊過程,而finishBeanFactoryInitialization方法是對註冊後的Bean定義中的預實例化(lazy-init=false,Spring默認就是預實例化,即爲true)的Bean進行處理的地方。

(2).finishBeanFactoryInitialization處理預實例化Bean:

當Bean定義資源被載入IoC容器以後,容器將Bean定義資源解析爲容器內部的數據結構BeanDefinition註冊到容器中,AbstractApplicationContext類中的finishBeanFactoryInitialization方法對配置了預實例化屬性的Bean進行預初始化過程,源碼以下:

//對配置了lazy-init屬性的Bean進行預實例化處理  
   protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {  
       //這是Spring3之後新加的代碼,爲容器指定一個轉換服務(ConversionService)  
       //在對某些Bean屬性進行轉換時使用  
       if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&  
               beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {  
           beanFactory.setConversionService(  
                   beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));  
       }  
       //爲了類型匹配,中止使用臨時的類加載器  
       beanFactory.setTempClassLoader(null);  
       //緩存容器中全部註冊的BeanDefinition元數據,以防被修改  
       beanFactory.freezeConfiguration();  
       //對配置了lazy-init屬性的單態模式Bean進行預實例化處理  
       beanFactory.preInstantiateSingletons();  
    }

ConfigurableListableBeanFactory是一個接口,其preInstantiateSingletons方法由其子類DefaultListableBeanFactory提供。

(3)、DefaultListableBeanFactory對配置lazy-init屬性單態Bean的預實例化:

1//對配置lazy-init屬性單態Bean的預實例化  
2public void preInstantiateSingletons() throws BeansException {  
       if (this.logger.isInfoEnabled()) {  
           this.logger.info("Pre-instantiating singletons in " + this);  
       }  
       //在對配置lazy-init屬性單態Bean的預實例化過程當中,必須多線程同步,以確保數據一致性  
       synchronized (this.beanDefinitionMap) {  
           for (String beanName : this.beanDefinitionNames) {  
               //獲取指定名稱的Bean定義  
               RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);  
               //Bean不是抽象的,是單態模式的,且lazy-init屬性配置爲false  
               if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {  
                   //若是指定名稱的bean是建立容器的Bean  
                   if (isFactoryBean(beanName)) {  
                   //FACTORY_BEAN_PREFIX=」&」,當Bean名稱前面加」&」符號  
                  //時,獲取的是產生容器對象自己,而不是容器產生的Bean.  
                  //調用getBean方法,觸發容器對Bean實例化和依賴注入過程  
                       final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);  
                       //標識是否須要預實例化  
                       boolean isEagerInit;  
                       if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {  
                           //一個匿名內部類  
                           isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {  
                               public Boolean run() {  
                                   return ((SmartFactoryBean) factory).isEagerInit();  
                               }  
                           }, getAccessControlContext());  
                       }  
                       else {  
                           isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();   
                       }  
                       if (isEagerInit) {  
                          //調用getBean方法,觸發容器對Bean實例化和依賴注入過程  
                           getBean(beanName);  
                       }  
                   }  
                   else {  
                        //調用getBean方法,觸發容器對Bean實例化和依賴注入過程  
                       getBean(beanName);  
                   }  
               }  
           }  
       }  
    }

經過對lazy-init處理源碼的分析,咱們能夠看出,若是設置了lazy-init屬性,則容器在完成Bean定義的註冊以後,會經過getBean方法,觸發對指定Bean的初始化和依賴注入過程,這樣當應用第一次向容器索取所需的Bean時,容器再也不須要對Bean進行初始化和依賴注入,直接從已經完成實例化和依賴注入的Bean中取一個線程的Bean,這樣就提升了第一次獲取Bean的性能。

三、FactoryBean的實現:

在Spring中,有兩個很容易混淆的類:BeanFactory和FactoryBean。 BeanFactory:Bean工廠,是一個工廠(Factory),咱們Spring IoC容器的最頂層接口就是這個BeanFactory,它的做用是管理Bean,即實例化、定位、配置應用程序中的對象及創建這些對象間的依賴。

FactoryBean:工廠Bean,是一個Bean,做用是產生其餘bean實例。一般狀況下,這種bean沒有什麼特別的要求,僅須要提供一個工廠方法,該方法用來返回其餘bean實例。一般狀況下,bean無須本身實現工廠模式,Spring容器擔任工廠角色;但少數狀況下,容器中的bean自己就是工廠,其做用是產生其它bean實例。

當用戶使用容器自己時,可使用轉義字符」&」來獲得FactoryBean自己,以區別經過FactoryBean產生的實例對象和FactoryBean對象自己。在BeanFactory中經過以下代碼定義了該轉義字符:

StringFACTORY_BEAN_PREFIX = "&";

若是myJndiObject是一個FactoryBean,則使用&myJndiObject獲得的是myJndiObject對象,而不是myJndiObject產生出來的對象。

(1).FactoryBean的源碼以下:

//工廠Bean,用於產生其餘對象  
public interface FactoryBean<T> {  
   //獲取容器管理的對象實例  
    T getObject() throws Exception;  
    //獲取Bean工廠建立的對象的類型  
    Class<?> getObjectType();  
    //Bean工廠建立的對象是不是單態模式,若是是單態模式,則整個容器中只有一個實例  
   //對象,每次請求都返回同一個實例對象  
    boolean isSingleton();  
}

(2). AbstractBeanFactory的getBean方法調用FactoryBean:

在前面咱們分析Spring Ioc容器實例化Bean並進行依賴注入過程的源碼時,提到在getBean方法觸發容器實例化Bean的時候會調用AbstractBeanFactory的doGetBean方法來進行實例化的過程,源碼以下:

//真正實現向IoC容器獲取Bean的功能,也是觸發依賴注入功能的地方    
     @SuppressWarnings("unchecked")    
     protected <T> T doGetBean(    
             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)    
             throws BeansException {    
         //根據指定的名稱獲取被管理Bean的名稱,剝離指定名稱中對容器的相關依賴    
         //若是指定的是別名,將別名轉換爲規範的Bean名稱    
         final String beanName = transformedBeanName(name);    
         Object bean;    
       //先從緩存中取是否已經有被建立過的單態類型的Bean,對於單態模式的Bean整    
           //個IoC容器中只建立一次,不須要重複建立    
         Object sharedInstance = getSingleton(beanName);    
         //IoC容器建立單態模式Bean實例對象    
         if (sharedInstance != null && args == null) {    
             if (logger.isDebugEnabled()) {    
             //若是指定名稱的Bean在容器中已有單態模式的Bean被建立,直接返回    
                   //已經建立的Bean    
                 if (isSingletonCurrentlyInCreation(beanName)) {    
                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +    
                             "' that is not fully initialized yet - a consequence of a circular reference");    
                 }    
                 else {    
                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");    
                 }    
             }    
             //獲取給定Bean的實例對象,主要是完成FactoryBean的相關處理   
             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);    
         }    
        ……  
    }  
   //獲取給定Bean的實例對象,主要是完成FactoryBean的相關處理 
   protected Object getObjectForBeanInstance(  
           Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {  
       //容器已經獲得了Bean實例對象,這個實例對象多是一個普通的Bean,也多是  
       //一個工廠Bean,若是是一個工廠Bean,則使用它建立一個Bean實例對象,若是  
       //調用自己就想得到一個容器的引用,則指定返回這個工廠Bean實例對象  
       //若是指定的名稱是容器的解引用(dereference,便是對象自己而非內存地址),  
       //且Bean實例也不是建立Bean實例對象的工廠Bean  
       if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {  
           throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());  
       }  
       //若是Bean實例不是工廠Bean,或者指定名稱是容器的解引用,調用者向獲取對  
       //容器的引用,則直接返回當前的Bean實例  
       if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {  
           return beanInstance;  
       }  
   //處理指定名稱不是容器的解引用,或者根據名稱獲取的Bean實例對象是一個工廠Bean  
   //使用工廠Bean建立一個Bean的實例對象  
       Object object = null;  
       if (mbd == null) {  
           //從Bean工廠緩存中獲取給定名稱的Bean實例對象  
           object = getCachedObjectForFactoryBean(beanName);  
       }  
       //讓Bean工廠生產給定名稱的Bean對象實例  
       if (object == null) {  
           FactoryBean factory = (FactoryBean) beanInstance;  
           //若是從Bean工廠生產的Bean是單態模式的,則緩存  
           if (mbd == null && containsBeanDefinition(beanName)) {  
               //從容器中獲取指定名稱的Bean定義,若是繼承基類,則合併基類相關屬性  
               mbd = getMergedLocalBeanDefinition(beanName);  
           }  
           //若是從容器獲得Bean定義信息,而且Bean定義信息不是虛構的,則讓工廠  
           //Bean生產Bean實例對象  
           boolean synthetic = (mbd != null && mbd.isSynthetic());  
           //調用FactoryBeanRegistrySupport類的getObjectFromFactoryBean  
           //方法,實現工廠Bean生產Bean對象實例的過程  
           object = getObjectFromFactoryBean(factory, beanName, !synthetic);  
       }  
       return object;  
    }

在上面獲取給定Bean的實例對象的getObjectForBeanInstance方法中,會調用FactoryBeanRegistrySupport類的getObjectFromFactoryBean方法,該方法實現了Bean工廠生產Bean實例對象。

Dereference(解引用):一個在C/C++中應用比較多的術語,在C++中,」*」是解引用符號,而」&」是引用符號,解引用是指變量指向的是所引用對象的自己數據,而不是引用對象的內存地址。

(3)、AbstractBeanFactory生產Bean實例對象:

AbstractBeanFactory類中生產Bean實例對象的主要源碼以下:

//Bean工廠生產Bean實例對象  
   protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {  
       //Bean工廠是單態模式,而且Bean工廠緩存中存在指定名稱的Bean實例對象  
       if (factory.isSingleton() && containsSingleton(beanName)) {  
           //多線程同步,以防止數據不一致  
           synchronized (getSingletonMutex()) {  
               //直接從Bean工廠緩存中獲取指定名稱的Bean實例對象  
               Object object = this.factoryBeanObjectCache.get(beanName);  
               //Bean工廠緩存中沒有指定名稱的實例對象,則生產該實例對象  
               if (object == null) {  
                   //調用Bean工廠的getObject方法生產指定Bean的實例對象  
                   object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
                   //將生產的實例對象添加到Bean工廠緩存中  
                   this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));  
               }  
               return (object != NULL_OBJECT ? object : null);  
           }  
       }  
       //調用Bean工廠的getObject方法生產指定Bean的實例對象  
       else {  
           return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);  
       }  
   }  
   //調用Bean工廠的getObject方法生產指定Bean的實例對象  
   private Object doGetObjectFromFactoryBean(  
           final FactoryBean factory, final String beanName, final boolean shouldPostProcess)  
           throws BeanCreationException {  
       Object object;  
       try {  
           if (System.getSecurityManager() != null) {  
               AccessControlContext acc = getAccessControlContext();  
               try {  
                   //實現PrivilegedExceptionAction接口的匿名內置類  
                   //根據JVM檢查權限,而後決定BeanFactory建立實例對象  
                   object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
                       public Object run() throws Exception {  
                               //調用BeanFactory接口實現類的建立對象方法  
                               return factory.getObject();  
                           }  
                       }, acc);  
               }  
               catch (PrivilegedActionException pae) {  
                   throw pae.getException();  
               }  
           }  
           else {  
               //調用BeanFactory接口實現類的建立對象方法  
               object = factory.getObject();  
           }  
       }  
       catch (FactoryBeanNotInitializedException ex) {  
           throw new BeanCurrentlyInCreationException(beanName, ex.toString());  
       }  
       catch (Throwable ex) {  
           throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);  
       }  
       //建立出來的實例對象爲null,或者由於單態對象正在建立而返回null  
       if (object == null && isSingletonCurrentlyInCreation(beanName)) {  
           throw new BeanCurrentlyInCreationException(  
                   beanName, "FactoryBean which is currently in creation returned null from getObject");  
       }  
       //爲建立出來的Bean實例對象添加BeanPostProcessor後置處理器  
       if (object != null && shouldPostProcess) {  
           try {  
               object = postProcessObjectFromFactoryBean(object, beanName);  
           }  
           catch (Throwable ex) {  
               throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);  
           }  
       }  
       return object;  
    }

從上面的源碼分析中,咱們能夠看出,BeanFactory接口調用其實現類的getObject方法來實現建立Bean實例對象的功能。

(4).工廠Bean的實現類getObject方法建立Bean實例對象:

FactoryBean的實現類有很是多,好比:Proxy、RMI、JNDI、ServletContextFactoryBean等等,FactoryBean接口爲Spring容器提供了一個很好的封裝機制,具體的getObject有不一樣的實現類根據不一樣的實現策略來具體提供,咱們分析一個最簡單的AnnotationTestFactoryBean的實現源碼:

public class AnnotationTestBeanFactory implements FactoryBean<IJmxTestBean> {  
       private final FactoryCreatedAnnotationTestBean instance = new FactoryCreatedAnnotationTestBean();  
       public AnnotationTestBeanFactory() {  
           this.instance.setName("FACTORY");  
       }  
       //AnnotationTestBeanFactory產生Bean實例對象的實現  
       public IJmxTestBean getObject() throws Exception {  
           return this.instance;  
       }  
       public Class<? extends IJmxTestBean> getObjectType() {  
           return FactoryCreatedAnnotationTestBean.class;  
       }  
       public boolean isSingleton() {  
           return true;  
       }  
     }

其餘的Proxy,RMI,JNDI等等,都是根據相應的策略提供getObject的實現。這裏不作一一分析,這已經不是Spring的核心功能,有須要的時候再去深刻研究。

4.BeanPostProcessor後置處理器的實現:

BeanPostProcessor後置處理器是Spring IoC容器常用到的一個特性,這個Bean後置處理器是一個監聽器,能夠監聽容器觸發的Bean聲明週期事件。後置處理器向容器註冊之後,容器中管理的Bean就具有了接收IoC容器事件回調的能力。

BeanPostProcessor的使用很是簡單,只須要提供一個實現接口BeanPostProcessor的實現類,而後在Bean的配置文件中設置便可。

(1).BeanPostProcessor的源碼以下:

package org.springframework.beans.factory.config;  
   import org.springframework.beans.BeansException;  
   public interface BeanPostProcessor {  
       //爲在Bean的初始化前提供回調入口  
       Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;  
       //爲在Bean的初始化以後提供回調入口  
       Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;  
     }

這兩個回調的入口都是和容器管理的Bean的生命週期事件緊密相關,能夠爲用戶提供在Spring IoC容器初始化Bean過程當中自定義的處理操做。

(2).AbstractAutowireCapableBeanFactory類對容器生成的Bean添加後置處理器:

BeanPostProcessor後置處理器的調用發生在Spring IoC容器完成對Bean實例對象的建立和屬性的依賴注入完成以後,在對Spring依賴注入的源碼分析過程當中咱們知道,當應用程序第一次調用getBean方法(lazy-init預實例化除外)向Spring IoC容器索取指定Bean時觸發Spring IoC容器建立Bean實例對象並進行依賴注入的過程,其中真正實現建立Bean對象並進行依賴注入的方法是AbstractAutowireCapableBeanFactory類的doCreateBean方法,主要源碼以下:

//真正建立Bean的方法  
   protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
       //建立Bean實例對象  
       ……  
       try {  
           //對Bean屬性進行依賴注入  
           populateBean(beanName, mbd, instanceWrapper);  
           if (exposedObject != null) {  
               //在對Bean實例對象生成和依賴注入完成之後,開始對Bean實例對象  
              //進行初始化 ,爲Bean實例對象應用BeanPostProcessor後置處理器  
              exposedObject = initializeBean(beanName, exposedObject, mbd);  
           }  
       }  
       catch (Throwable ex) {  
           if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
               throw (BeanCreationException) ex;  
           }  
       ……  
       //爲應用返回所須要的實例對象  
       return exposedObject;  
    }

從上面的代碼中咱們知道,爲Bean實例對象添加BeanPostProcessor後置處理器的入口的是initializeBean方法。

(3).initializeBean方法爲容器產生的Bean實例對象添加BeanPostProcessor後置處理器:

一樣在AbstractAutowireCapableBeanFactory類中,initializeBean方法實現爲容器建立的Bean實例對象添加BeanPostProcessor後置處理器,源碼以下:

//初始容器建立的Bean實例對象,爲其添加BeanPostProcessor後置處理器  
   protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {  
       //JDK的安全機制驗證權限  
       if (System.getSecurityManager() != null) {  
           //實現PrivilegedAction接口的匿名內部類  
           AccessController.doPrivileged(new PrivilegedAction<Object>() {  
               public Object run() {  
                   invokeAwareMethods(beanName, bean);  
                   return null;  
               }  
           }, getAccessControlContext());  
       }  
       else {  
           //爲Bean實例對象包裝相關屬性,如名稱,類加載器,所屬容器等信息  
           invokeAwareMethods(beanName, bean);  
       }  
       Object wrappedBean = bean;  
       //對BeanPostProcessor後置處理器的postProcessBeforeInitialization  
       //回調方法的調用,爲Bean實例初始化前作一些處理  
       if (mbd == null || !mbd.isSynthetic()) {  
           wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);  
       }  
       //調用Bean實例對象初始化的方法,這個初始化方法是在Spring Bean定義配置  
       //文件中經過init-method屬性指定的  
       try {  
           invokeInitMethods(beanName, wrappedBean, mbd);  
       }  
       catch (Throwable ex) {  
           throw new BeanCreationException(  
                   (mbd != null ? mbd.getResourceDescription() : null),  
                   beanName, "Invocation of init method failed", ex);  
       }  
       //對BeanPostProcessor後置處理器的postProcessAfterInitialization  
       //回調方法的調用,爲Bean實例初始化以後作一些處理  
       if (mbd == null || !mbd.isSynthetic()) {  
           wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);  
       }  
       return wrappedBean;  
   }  
   //調用BeanPostProcessor後置處理器實例對象初始化以前的處理方法  
   public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)  
           throws BeansException {  
       Object result = existingBean;  
       //遍歷容器爲所建立的Bean添加的全部BeanPostProcessor後置處理器  
       for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
           //調用Bean實例全部的後置處理中的初始化前處理方法,爲Bean實例對象在  
           //初始化以前作一些自定義的處理操做  
           result = beanProcessor.postProcessBeforeInitialization(result, beanName);  
           if (result == null) {  
               return result;  
           }  
       }  
       return result;  
   }  
   //調用BeanPostProcessor後置處理器實例對象初始化以後的處理方法  
   public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)  
           throws BeansException {  
       Object result = existingBean;  
       //遍歷容器爲所建立的Bean添加的全部BeanPostProcessor後置處理器  
       for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {  
           //調用Bean實例全部的後置處理中的初始化後處理方法,爲Bean實例對象在  
           //初始化以後作一些自定義的處理操做  
           result = beanProcessor.postProcessAfterInitialization(result, beanName);  
           if (result == null) {  
               return result;  
           }  
       }  
       return result;  
    }

BeanPostProcessor是一個接口,其初始化前的操做方法和初始化後的操做方法均委託其實現子類來實現,在Spring中,BeanPostProcessor的實現子類很是的多,分別完成不一樣的操做,如:AOP面向切面編程的註冊通知適配器、Bean對象的數據校驗、Bean繼承屬性/方法的合併等等,咱們以最簡單的AOP切面織入來簡單瞭解其主要的功能。

(4).AdvisorAdapterRegistrationManager在Bean對象初始化後註冊通知適配器:

AdvisorAdapterRegistrationManager是BeanPostProcessor的一個實現類,其主要的做用爲容器中管理的Bean註冊一個面向切面編程的通知適配器,以便在Spring容器爲所管理的Bean進行面向切面編程時提供方便,其源碼以下:

//爲容器中管理的Bean註冊一個面向切面編程的通知適配器  
public class AdvisorAdapterRegistrationManager implements BeanPostProcessor {  
   //容器中負責管理切面通知適配器註冊的對象  
   private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();  
   public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {  
       this.advisorAdapterRegistry = advisorAdapterRegistry;  
   }  
   //BeanPostProcessor在Bean對象初始化前的操做  
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {  
       //沒有作任何操做,直接返回容器建立的Bean對象  
       return bean;  
   }  
   //BeanPostProcessor在Bean對象初始化後的操做  
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {  
       if (bean instanceof AdvisorAdapter){  
           //若是容器建立的Bean實例對象是一個切面通知適配器,則向容器的註冊
              this.advisorAdapterRegistry.registerAdvisorAdapter((AdvisorAdapter) bean);  
       }  
       return bean;  
   }  
}

其餘的BeanPostProcessor接口實現類的也相似,都是對Bean對象使用到的一些特性進行處理,或者向IoC容器中註冊,爲建立的Bean實例對象作一些自定義的功能增長,這些操做是容器初始化Bean時自動觸發的,不須要認爲的干預。

5.Spring IoC容器autowiring實現原理:

Spring IoC容器提供了兩種管理Bean依賴關係的方式:

a. 顯式管理:經過BeanDefinition的屬性值和構造方法實現Bean依賴關係管理。

b. autowiring:Spring IoC容器的依賴自動裝配功能,不須要對Bean屬性的依賴關係作顯式的聲明,只須要在配置好autowiring屬性,IoC容器會自動使用反射查找屬性的類型和名稱,而後基於屬性的類型或者名稱來自動匹配容器中管理的Bean,從而自動地完成依賴注入。

經過對autowiring自動裝配特性的理解,咱們知道容器對Bean的自動裝配發生在容器對Bean依賴注入的過程當中。在前面對Spring IoC容器的依賴注入過程源碼分析中,咱們已經知道了容器對Bean實例對象的屬性注入的處理髮生在AbstractAutoWireCapableBeanFactory類中的populateBean方法中,咱們經過程序流程分析autowiring的實現原理:

(1). AbstractAutoWireCapableBeanFactory對Bean實例進行屬性依賴注入: 應用第一次經過getBean方法(配置了lazy-init預實例化屬性的除外)向IoC容器索取Bean時,容器建立Bean實例對象,而且對Bean實例對象進行屬性依賴注入,AbstractAutoWireCapableBeanFactory的populateBean方法就是實現Bean屬性依賴注入的功能,其主要源碼以下:

protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {  
       //獲取Bean定義的屬性值,並對屬性值進行處理  
       PropertyValues pvs = mbd.getPropertyValues();  
       ……  
       //對依賴注入處理,首先處理autowiring自動裝配的依賴注入  
       if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  
               mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
           MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
           //根據Bean名稱進行autowiring自動裝配處理  
           if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
               autowireByName(beanName, mbd, bw, newPvs);  
           }  
           //根據Bean類型進行autowiring自動裝配處理  
           if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
               autowireByType(beanName, mbd, bw, newPvs);  
           }  
       }  
       //對非autowiring的屬性進行依賴注入處理  
        ……  
    }

(2).Spring IoC容器根據Bean名稱或者類型進行autowiring自動依賴注入:

//根據名稱對屬性進行自動依賴注入  
   protected void autowireByName(  
           String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {  
        //對Bean對象中非簡單屬性(不是簡單繼承的對象,如8中原始類型,字符串,URL等//都是簡單屬性)進行處理  
       String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);  
       for (String propertyName : propertyNames) {  
           //若是Spring IoC容器中包含指定名稱的Bean  
           if (containsBean(propertyName)) {  
                //調用getBean方法向IoC容器索取指定名稱的Bean實例,迭代觸發屬性的//初始化和依賴注入  
               Object bean = getBean(propertyName);  
               //爲指定名稱的屬性賦予屬性值  
               pvs.add(propertyName, bean);  
               //指定名稱屬性註冊依賴Bean名稱,進行屬性依賴注入  
               registerDependentBean(propertyName, beanName);  
               if (logger.isDebugEnabled()) {  
                   logger.debug("Added autowiring by name from bean name '" + beanName +  
                           "' via property '" + propertyName + "' to bean named '" + propertyName + "'");  
               }  
           }  
           else {  
               if (logger.isTraceEnabled()) {  
                   logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +  
                           "' by name: no matching bean found");  
               }  
           }  
       }  
   }  
   //根據類型對屬性進行自動依賴注入  
   protected void autowireByType(  
           String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {  
       //獲取用戶定義的類型轉換器  
       TypeConverter converter = getCustomTypeConverter();  
       if (converter == null) {  
           converter = bw;  
       }  
       //存放解析的要注入的屬性  
       Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);  
         //對Bean對象中非簡單屬性(不是簡單繼承的對象,如8中原始類型,字符  
        //URL等都是簡單屬性)進行處理  
       String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);  
       for (String propertyName : propertyNames) {  
           try {  
               //獲取指定屬性名稱的屬性描述器  
               PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);  
               //不對Object類型的屬性進行autowiring自動依賴注入  
               if (!Object.class.equals(pd.getPropertyType())) {  
                   //獲取屬性的setter方法  
                   MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);  
                   //檢查指定類型是否能夠被轉換爲目標對象的類型  
                   boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());  
                   //建立一個要被注入的依賴描述  
                   DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);  
                   //根據容器的Bean定義解析依賴關係,返回全部要被注入的Bean對象  
                   Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);  
                   if (autowiredArgument != null) {  
                       //爲屬性賦值所引用的對象  
                       pvs.add(propertyName, autowiredArgument);  
                   }  
                   for (String autowiredBeanName : autowiredBeanNames) {  
                       //指定名稱屬性註冊依賴Bean名稱,進行屬性依賴注入  
                       registerDependentBean(autowiredBeanName, beanName);  
                       if (logger.isDebugEnabled()) {  
                           logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +  
                                   propertyName + "' to bean named '" + autowiredBeanName + "'");  
                       }  
                   }  
                   //釋放已自動注入的屬性  
                   autowiredBeanNames.clear();  
               }  
           }  
           catch (BeansException ex) {  
               throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);  
           }  
       }  
    }

經過上面的源碼分析,咱們能夠看出來經過屬性名進行自動依賴注入的相對比經過屬性類型進行自動依賴注入要稍微簡單一些,可是真正實現屬性注入的是DefaultSingletonBeanRegistry類的registerDependentBean方法。

(3).DefaultSingletonBeanRegistry的registerDependentBean方法對屬性注入:

//爲指定的Bean注入依賴的Bean  
   public void registerDependentBean(String beanName, String dependentBeanName) {  
       //處理Bean名稱,將別名轉換爲規範的Bean名稱  
       String canonicalName = canonicalName(beanName);  
       //多線程同步,保證容器內數據的一致性  
       //先從容器中:bean名稱-->所有依賴Bean名稱集合找查找給定名稱Bean的依賴Bean  
       synchronized (this.dependentBeanMap) {  
           //獲取給定名稱Bean的全部依賴Bean名稱  
           Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);  
           if (dependentBeans == null) {  
               //爲Bean設置依賴Bean信息  
               dependentBeans = new LinkedHashSet<String>(8);  
               this.dependentBeanMap.put(canonicalName, dependentBeans);  
           }  
           //向容器中:bean名稱-->所有依賴Bean名稱集合添加Bean的依賴信息  
           //即,將Bean所依賴的Bean添加到容器的集合中  
           dependentBeans.add(dependentBeanName);  
       }  
         //從容器中:bean名稱-->指定名稱Bean的依賴Bean集合找查找給定名稱  
        //Bean的依賴Bean  
       synchronized (this.dependenciesForBeanMap) {  
           Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(dependentBeanName);  
           if (dependenciesForBean == null) {  
               dependenciesForBean = new LinkedHashSet<String>(8);  
               this.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);  
           }  
           //向容器中:bean名稱-->指定Bean的依賴Bean名稱集合添加Bean的依賴信息  
           //即,將Bean所依賴的Bean添加到容器的集合中  
           dependenciesForBean.add(canonicalName);  
       }  
    }

經過對autowiring的源碼分析,咱們能夠看出,autowiring的實現過程:

a. 對Bean的屬性迭代調用getBean方法,完成依賴Bean的初始化和依賴注入。

b. 將依賴Bean的屬性引用設置到被依賴的Bean屬性上。

c. 將依賴Bean的名稱和被依賴Bean的名稱存儲在IoC容器的集合中。

Spring IoC容器的autowiring屬性自動依賴注入是一個很方便的特性,能夠簡化開發時的配置,可是凡是都有兩面性,自動屬性依賴注入也有不足,首先,Bean的依賴關係在配置文件中沒法很清楚地看出來,對於維護形成必定困難。其次,因爲自動依賴注入是Spring容器自動執行的,容器是不會智能判斷的,若是配置不當,將會帶來沒法預料的後果,因此自動依賴注入特性在使用時仍是綜合考慮。

相關文章
相關標籤/搜索