官术网_书友最值得收藏!

2.4 IoC容器的依賴注入

上面對IoC容器的初始化過程進行了詳細的分析,這個初始化過程完成的主要工作是在IoC容器中建立BeanDefinition數據映射。在此過程中并沒有看到IoC容器對Bean依賴關系進行注入,接下來分析一下IoC容器是怎樣對Bean的依賴關系進行注入的。

假設當前IoC容器已經載入了用戶定義的Bean信息,開始分析依賴注入的原理。首先,注意到依賴注入的過程是用戶第一次向IoC容器索要Bean時觸發的,當然也有例外,也就是我們可以在BeanDefinition信息中通過控制lazy-init屬性來讓容器完成對Bean的預實例化。這個預實例化實際上也是一個完成依賴注入的過程,但它是在初始化的過程中完成的,稍后我們會詳細分析這個預實例化的處理。當用戶向IoC容器索要Bean時,如果讀者還有印象,那么一定還記得在基本的IoC容器接口BeanFactory中,有一個getBean的接口定義,這個接口的實現就是觸發依賴注入發生的地方。為了進一步了解這個依賴注入過程的實現,下面從DefaultListableBeanFactory的基類AbstractBeanFactory入手去看看getBean的實現,如代碼清單2-22所示。

代碼清單2-22 getBean觸發的依賴注入

        //--------------------------------------------------------------------
        // 這里是對 BeanFactory接口的實現,比如getBean接口方法
        // 這些getBean接口方法最終是通過調用doGetBean來實現的
        //--------------------------------------------------------------------
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
        public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
            return doGetBean(name, requiredType, null, false);
        }
        public Object getBean(String name, Object... args) throws BeansException {
            return doGetBean(name, null, args, false);
        }
        public <T> T getBean(String name, Class<T> requiredType, Object[] args)
        throws BeansException {
            return doGetBean(name, requiredType, args, false);
        }
        //這里是實際取得Bean的地方,也是觸發依賴注入發生的地方
        protected <T> T doGetBean(
                final String name, final Class<T> requiredType, final Object[] args, boolean
        typeCheckOnly)
                throws BeansException {
            final String beanName = transformedBeanName(name);
            Object bean;
            //先從緩存中取得Bean,處理那些已經被創建過的單件模式的Bean,對這種Bean的請求不需要
            //重復地創建
            Object sharedInstance = getSingleton(beanName);
            if (sharedInstance != null && args == null) {
                if (logger.isDebugEnabled()) {
                    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 + "'");
                    }
                }
            /*這里的getObjectForBeanInstance完成的是FactoryBean的相關處理,以取得
            FactoryBean的生產結果,  BeanFactoryFactoryBean的區別已經在前面講過,這個過程在后
            面還會詳細地分析*/
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            }
            else {
                if (isPrototypeCurrentlyInCreation(beanName)) {
                    throw new BeanCurrentlyInCreationException(beanName);
                }
            /*這里對IoC容器中的BeanDefintion是否存在進行檢查,檢查是否能在當前的BeanFactory中取
              得需要的Bean。如果在當前的工廠中取不到,則到雙親BeanFactory中去取;如果當前的雙親工
              廠取不到,那就順著雙親BeanFactory鏈一直向上查找*/
                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);
                }
                //這里根據Bean的名字取得BeanDefinition
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
                //獲取當前Bean的所有依賴Bean,這樣會觸發getBean的遞歸調用,直到取到一個沒有
                //任何依賴的Bean為止
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        getBean(dependsOnBean);
                        registerDependentBean(dependsOnBean, beanName);
                    }
                }
                /*這里通過調用createBean方法創建Singleton  bean的實例,這里有一個回調函數
                  getObject,會在getSingleton中調用ObjectFactorycreateBean*/
                //下面會進入到createBean中進行詳細分析
                if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory() {
                        public Object getObject() throws BeansException {
                              try {
                                  return createBean(beanName, mbd, args);
                              }
                              catch (BeansException ex) {
                                  destroySingleton(beanName);
                                  throw ex;
                              }
                    }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }
                //這里是創建prototype bean的地方
                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 {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    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 = 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進行類型檢查,如果沒有問題,就返回這個新創建的Bean,這個Bean已經
              //是包含了依賴關系的Bean
              if (requiredType != null && bean != null && !requiredType.
              isAssignableFrom(bean.getClass())) {
              throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
              }
              return (T) bean;
        }

這個就是依賴注入的入口,在這里觸發了依賴注入,而依賴注入的發生是在容器中的BeanDefinition數據已經建立好的前提下進行的。“程序=數據+算法,”很經典的一句話,前面的BeanDefinition就是數據,下面看看這些數據是怎樣為依賴注入服務的。雖然依賴注入的過程不涉及復雜的算法問題,但這個過程也不簡單,因為我們都知道,對于IoC容器的使用,Spring提供了許多的參數配置,每一個參數配置實際上代表了一個IoC容器的實現特性,這些特性的實現很多都需要在依賴注入的過程中或者對Bean進行生命周期管理的過程中完成。盡管可以用最簡單的方式來描述IoC容器,將它視為一個hashMap,但只能說這個hashMap是容器的最基本的數據結構,而不是IoC容器的全部。Spring IoC容器作為一個產品,其價值體現在一系列相關的產品特性上,這些產品特性以依賴反轉模式的實現為核心,為用戶更好地使用依賴反轉提供便利,從而實現了一個完整的IoC容器產品。這些產品特性的實現并不是一個簡單的過程,它提供了一個成熟的IoC容器產品供用戶使用。所以,盡管Spring IoC容器沒有什么獨特的算法,但卻可以看成是一個成功的軟件工程產品,有許多值得我們學習的地方。

關于這個依賴注入的詳細過程會在下面進行分析,在圖2-14中可以看到依賴注入的一個大致過程。

圖2-14 依賴注入的過程

重點來說,getBean是依賴注入的起點,之后會調用createBean,下面通過createBean代碼來了解這個實現過程。在這個過程中,Bean對象會依據BeanDefinition定義的要求生成。在AbstractAutowireCapableBeanFactory中實現了這個createBean,createBean不但生成了需要的Bean,還對Bean初始化進行了處理,比如實現了在BeanDefinition中的init-method屬性定義,Bean后置處理器等。具體的過程如代碼清單2-23所示。

代碼清單2-23 AbstractAutowireCapableBeanFactory中的createBean

        protected Object createBean(final String beanName, final RootBeanDefinition
        mbd, final Object[] args)
            throws BeanCreationException {
        AccessControlContext acc = AccessController.getContext();
        return AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating instance of bean '" + beanName + "'");
                }
                // 這里判斷需要創建的Bean是否可以實例化,這個類是否可以通過類裝載器來載入
                resolveBeanClass(mbd, beanName);
                    try {
                    mbd.prepareMethodOverrides();
                }
                catch (BeanDefinitionValidationException ex) {
                    throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
                            beanName, "Validation of method overrides failed", ex);
                }
                try {
                    // 如果Bean配置了PostProcessor,那么這里返回的是一個proxy
                    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;
            }
        }, acc);
        }
        //接著到doCreateBean中去看看Bean是怎樣生成的
            protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd,
            final Object[] args) {
                // 這個BeanWrapper是用來持有創建出來的Bean對象的
                BeanWrapper instanceWrapper = null;
                //如果是Singleton,先把緩存中的同名Bean清除
                if(mbd.isSingleton()) {
                    instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
                }
                //這里是創建Bean的地方,由createBeanInstance來完成
                if (instanceWrapper == null) {
                    instanceWrapper = createBeanInstance(beanName, mbd, args);
                }
                final Object bean = (instanceWrapper != null ?
                instanceWrapper.getWrappedInstance() : null);
                Class beanType = (instanceWrapper != null ? instanceWrapper.
                getWrappedClass() : null);
            synchronized (mbd.postProcessingLock) {
                if (!mbd.postProcessed) {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                    mbd.postProcessed = true;
                }
            }
            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 {
                populateBean(beanName, mbd, instanceWrapper);
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
            catch (Throwable ex) {
                iflt@span b=1> (exlt@span b=1> instanceoflt@span b=1> BeanCreationExceptionlt@span b=1> &&lt@span b=1> beanName.equals
                (((BeanCreationException) ex).getBeanName())) {
                    throw (BeanCreationException) ex;
                }
                else {
                    throw new BeanCreationException(mbd.getResourceDescription(),
                    beanName, "Initialization of bean failed", ex);
                }
            }
            if (earlySingletonExposure) {
                Object earlySingletonReference = getSingleton(beanName, false);
                if (earlySingletonReference != null) {
                    if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                    }
                    else if (!this.allowRawInjectionDespiteWrapping &&
                    hasDependentBean(beanName)) {
                        String[] dependentBeans = getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new
                        LinkedHashSet<String>(dependentBeans.length);
                        for (String dependentBean : dependentBeans) {
                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                            actualDependentBeans.add(dependentBean);
                                    }
                            }
                            if (!actualDependentBeans.isEmpty()) {
                                throw new BeanCurrentlyInCreationException(beanName,
                                      "Bean with name '" + beanName + "' has been injected into
                                      other beans [" +
                                      StringUtils.collectionToCommaDelimitedString
                                      (actualDependentBeans) +
                                      "] in its raw version as part of a circular
                                      reference, but has eventually been " +
                                      "wrapped. This means that said other beans do not
                                      use the final version of the " +
                                      "bean. This is often the result of over-eager type
                                      matching - consider using " +
                                      "'getBeanNamesOfType' with the 'allowEagerInit'
                                      flag turned off, for example.");
                            }
                    }
                }
            }
            try {
                registerDisposableBeanIfNecessary(beanName, bean, mbd);
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
        "Invalid destruction signature", ex);
            }
            return exposedObject;
        }

在這里我們看到,與依賴注入關系特別密切的方法有createBeanInstance和populateBean,下面分別介紹這兩個方法。在createBeanInstance中生成了Bean所包含的Java對象,這個對象的生成有很多種不同的方式,可以通過工廠方法生成,也可以通過容器的autowire特性生成,這些生成方式都是由相關的BeanDefinition來指定的。如代碼清單2-24所示,可以看到不同生成方式對應的實現。

代碼清單2-24 Bean包含的Java對象的生成

        protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition
        mbd, Object[] args) {
        // 確認需要創建的Bean實例的類可以實例化
        Class beanClass = resolveBeanClass(mbd, beanName);
        //這里使用工廠方法對Bean進行實例化
        if (mbd.getFactoryMethodName() != null)   {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }
        if (mbd.resolvedConstructorOrFactoryMethod != null) {
            if (mbd.constructorArgumentsResolved) {
                return autowireConstructor(beanName, mbd, null, args);
            }
            else {
                return instantiateBean(beanName, mbd);
            }
        }
        // 使用構造函數進行實例化
        Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
            }
            // 使用默認的構造函數對Bean進行實例化
            return instantiateBean(beanName, mbd);
        }
        //最常見的實例化過程instantiateBean
        protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
        //使用默認的實例化策略對Bean進行實例化,默認的實例化策略是
        //CglibSubclassingInstantiationStrategy,也就是使用CGLIB來對Bean進行實例化
            //接著再看CglibSubclassingInstantiationStrategy的實現
            try {
                Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
                BeanWrapper bw = new BeanWrapperImpl(beanInstance);
                initBeanWrapper(bw);
                return bw;
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Instantiation of bean failed", ex);
            }
        }

這里用CGLIB對Bean進行實例化。CGLIB是一個常用的字節碼生成器的類庫,它提供了一系列的API來提供生成和轉換Java的字節碼的功能。在Spring AOP中也使用CGLIB對Java的字節碼進行增強。在IoC容器中,要了解怎樣使用CGLIB來生成Bean對象,需要看一下SimpleInstantiationStrategy類。這個Strategy是Spring用來生成Bean對象的默認類,它提供了兩種實例化Java對象的方法,一種是通過BeanUtils,它使用了JVM的反射功能,一種是通過前面提到的CGLIB來生成,如代碼清單2-25所示。

代碼清單2-25 使用SimpleInstantiationStrategy生成Java對象

        public class SimpleInstantiationStrategy implements InstantiationStrategy {
        public Object instantiate(
                RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
            if (beanDefinition.getMethodOverrides().isEmpty()) {
            //這里取得指定的構造器或者生成對象的工廠方法來對Bean進行實例化
                Constructor constructorToUse = (Constructor) beanDefinition.
                resolvedConstructorOrFactoryMethod;
                if (constructorToUse == null) {
                    Class clazz = beanDefinition.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class
                        is an interface");
                    }
                    try {
                        constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
                        beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
                    }
                    catch (Exception ex) {
                        throw new BeanInstantiationException(clazz, "No default
                        constructor found", ex);
                    }
                }
            //通過BeanUtils進行實例化,這個BeanUtils的實例化通過Constructor來實例化Bean,
            //BeanUtils中可以看到具體的調用ctor.newInstance(args)
                return BeanUtils.instantiateClass(constructorToUse, null);
            }
            else {
                //使用CGLIB來實例化對象
                return instantiateWithMethodInjection(beanDefinition, beanName, owner);
            }
        }

在cglibSubclassingInstantiationStrategy中可以看到具體的實例化過程和CGLIB的使用方法,這里就不對CGLIB的使用進行過多闡述了。如果讀者有興趣,可以去閱讀CGLIB的使用文檔,不過這里的Spring代碼可以為使用CGLIB提供很好的參考。這里的Enhancer類,已經是CGLIB的類了,通過這個Enhancer生成Java對象,使用的是Enhancer的create方法,如代碼清單2-26所示。

代碼清單2-26 使用CGLIB的Enhancer生成Java對象

        public Object instantiate(Constructor ctor, Object[] args) {
        //生成Enhancer對象,并為Enhancer對象設置生成Java對象的參數,比如基類、回調方法等
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(this.beanDefinition.getBeanClass());
            enhancer.setCallbackFilter(new CallbackFilterImpl());
            enhancer.setCallbacks(new Callback[] {
                      NoOp.INSTANCE,
                      new LookupOverrideMethodInterceptor(),
                      new ReplaceOverrideMethodInterceptor()
              });
              //使用CGLIBcreate生成實例化的Bean對象
              return (ctor == null) ?
                      enhancer.create() :
                      enhancer.create(ctor.getParameterTypes(), args);
        }

到這里已經分析了實例化Bean對象的整個過程。在實例化Bean對象生成的基礎上,再介紹一下Spring是怎樣對這些對象進行處理的,也就是Bean對象生成以后,怎樣把這些Bean對象的依賴關系設置好,完成整個依賴注入過程。這個過程涉及對各種Bean對象的屬性的處理過程(即依賴關系處理的過程),這些依賴關系處理的依據就是已經解析得到的BeanDefinition。要詳細了解這個過程,需要回到前面的populateBean方法,這個方法在AbstractAutowireCapableBeanFactory中的實現如代碼清單2-27所示。

代碼清單2-27 populateBean的實現

        protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {
        //這里取得在BeanDefinition中設置的property值,這些property來自對BeanDefinition的解析
        //具體的解析過程可以參看對載入和解析BeanDefinition的分析
              PropertyValues pvs = mbd.getPropertyValues();
              if (bw == null) {
                  if (!pvs.isEmpty()) {
                        throw new BeanCreationException(
                              mbd.getResourceDescription(), beanName, "Cannot apply
                              property values to null instance");
                  }
                  else {
                        return;
                  }
              }
              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的名字或者類型,
                  //來完成Beanautowire
                  if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                      autowireByName(beanName, mbd, bw, newPvs);
                  }
                  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);
                  if (hasInstAwareBpps) {
                      for (BeanPostProcessor bp : getBeanPostProcessors()) {
                          if (bp instanceof InstantiationAwareBeanPostProcessor) {
                                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBean
                                PostProcessor) 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);
        }
        //通過applyPropertyValues了解具體的對屬性行進行解析然后注入的過程
        protected void applyPropertyValues(String beanName, BeanDefinition mbd,
        BeanWrapper bw, PropertyValues pvs) {
              if (pvs == null || pvs.isEmpty()) {
                  return;
              }
              MutablePropertyValues mpvs = null;
              List<PropertyValue> original;
              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;
            }
            //注意這個BeanDefinitionValueResolverBeanDefinition的解析是在
            //這個valueResolver中完成的
            BeanDefinitionValueResolver valueResolver = new
            BeanDefinitionValueResolver(this, beanName, mbd, converter);
            //這里為解析值創建一個副本,副本的數據將會被注入到Bean
            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();
                      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 (originalValue instanceof TypedStringValue && convertible &&
                              !(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();
                  }
                  // 這里是依賴注入發生的地方,會在BeanWrapperImpl中完成
                  try {
                      bw.setPropertyValues(new MutablePropertyValues(deepCopy));
                  }
                  catch (BeansException ex) {
                      throw new BeanCreationException(
                              mbd.getResourceDescription(), beanName, "Error setting
                              property values", ex);
                  }
            }

這里通過使用BeanDefinitionResolver來對BeanDefinition進行解析,然后注入到property中。下面到BeanDefinitionValueResolver中去看一下解析過程的實現,以對Bean reference進行解析為例,如圖2-15所示,可以看到整個Resolve的過程。具體的對Bean reference進行解析的過程如代碼清單2-28所示。

圖2-15 Resolve的調用過程

代碼清單2-28 對Bean Reference的解析

        private Object resolveReference(Object argName, RuntimeBeanReference ref) {
            try {
            //RuntimeBeanReference取得reference的名字,這個RuntimeBeanReference是在
            //載入BeanDefinition時根據配置生成的
                  String refName = ref.getBeanName();
                  refName = String.valueOf(evaluate(refName));
                  //如果ref是在雙親IoC容器中,那就到雙親IoC容器中去獲取
                  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);
                  }
        //在當前IoC容器中去獲取Bean,這里會觸發一個getBean的過程,如果依賴注入沒有發生,這里會
        //觸發相應的依賴注入的發生
                  elselt@span b=1> {
                      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);
              }
        }
        //下面看一下對其他類型的屬性進行注入的例子,比如arraylist
        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.set(resolved, i,
                  resolveValueIfNecessary(
                                argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i +
                                BeanWrapper.PROPERTY_KEY_SUFFIX,
                                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++) {
                  resolved.add(
                  resolveValueIfNecessary(
                                argName + " with key " + BeanWrapper.PROPERTY_KEY_PREFIX + i +
                                BeanWrapper.PROPERTY_KEY_SUFFIX,
                                ml.get(i)));
              }
              return resolved;
        }

這兩種屬性的注入都調用了resolveValueIfNecessary,這個方法包含了所有對注入類型的處理。下面看一下resolveValueIfNecessary的實現,如代碼清單2-29所示。

代碼清單2-29 resolveValueIfNecessary的實現

        public Object resolveValueIfNecessary(Object argName, Object value) {
            //這里對RuntimeBeanReference進行解析,RuntimeBeanReference是在
            //BeanDefinition進行解析時生成的數據對象
            if (value instanceof RuntimeBeanReference) {
                  RuntimeBeanReference ref = (RuntimeBeanReference) value;
                  return resolveReference(argName, ref);
            }
            else if (value instanceof RuntimeBeanNameReference) {
                  String refName = ((RuntimeBeanNameReference) value).getBeanName();
                  refName = String.valueOf(evaluate(refName));
                  if (!this.beanFactory.containsBean(refName)) {
                      throw new BeanDefinitionStoreException(
                                "Invalid bean name '" + refName + "' in bean reference for " + argName);
                  }
                  return refName;
              }
              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);
              }
          //這里對ManageArray進行解析
              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);
                            }
                  }
                  else {
                        elementType = Object.class;
                  }
              }
              return resolveManagedArray(argName, (List<?>) value, elementType);
              }
          //這里對ManageList進行解析
              else if (value instanceof ManagedList) {
                  return resolveManagedList(argName, (List<?>) value);
              }
          //這里對ManageSet進行解析
              else if (value instanceof ManagedSet) {
                  return resolveManagedSet(argName, (Set<?>) value);
              }
          //這里對ManageMap進行解析
              else if (value instanceof ManagedMap) {
                  return resolveManagedMap(argName, (Map<?, ?>) value);
              }
          //這里對ManageProperties進行解析
              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 = ((TypedStringValue) propKey).getValue();
                        }
                        if (propValue instanceof TypedStringValue) {
                            propValue = ((TypedStringValue) propValue).getValue();
                        }
                        copy.put(propKey, propValue);
                    }
                    return copy;
              }
          //這里對TypedStringValue進行解析
              else if (value instanceof TypedStringValue) {
                    TypedStringValue typedStringValue = (TypedStringValue) value;
                    Object valueObject = evaluate(typedStringValue.getValue());
                    try {
                        Class resolvedTargetType = resolveTargetType(typedStringValue);
                        if (resolvedTargetType != null) {
                            return this.typeConverter.convertIfNecessary
                            (valueObject, resolvedTargetType);
                        }
                        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);
              }
          }
          //RuntimeBeanReference類型的注入在resolveReference
              private Object resolveReference(Object argName, RuntimeBeanReference ref) {
                    try {
              //RuntimeBeanReference取得reference的名字,這個RuntimeBeanReference是在
              //載入BeanDefinition時根據配置生成的
                    String refName = ref.getBeanName();
                    refName = String.valueOf(evaluate(refName));
              //如果ref是在雙親IoC容器中,那就到雙親IoC容器中去獲取
                    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);
                    }
          //在當前IoC容器中取得Bean,這里會觸發一個getBean的過程,如果依賴注入沒有發生,這里會
          //觸發相應的依賴注入的發生
                    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);
              }
          }
          //manageList的處理過程在resolveManagedList
          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(
                                    argName + " with key " + BeanWrapper.PROPERTY_
                                    KEY_PREFIX + i + BeanWrapper.PROPERTY_KEY_SUFFIX,
                                    ml.get(i)));
              }
              return resolved;
          }

在完成這個解析過程后,已經為依賴注入準備好了條件,這是真正把Bean對象設置到它所依賴的另一個Bean的屬性中去的地方,其中處理的屬性是各種各樣的。依賴注入的發生是在BeanWrapper的setPropertyValues中實現的,具體的完成卻是在BeanWrapper的子類BeanWrapperImpl中實現的,如代碼清單2-30所示。

代碼清單2-30 BeanWraper完成Bean的屬性值注入

        private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws
        BeansException {
            String propertyName = tokens.canonicalName;
            String actualName = tokens.actualName;
            if (tokens.keys != null) {
                  // 設置tokens的索引和keys
                  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;
                  //getPropertyValue取得Bean中對注入對象的引用,比如Array、List、Map、Set
                  try {
                      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()) {
                      Class requiredType = propValue.getClass().getComponentType();
                      int arrayIndex = Integer.parseInt(key);
                      Object oldValue = null;
                      try {
                          if (isExtractOldValueForEditor()) {
                                    oldValue = Array.get(propValue, arrayIndex);
                          }
                          Object convertedValue = this.typeConverterDelegate.
                          convertIfNecessary(
                              propertyName, oldValue, pv.getValue(), requiredType);
                          Array.set(propValue, Integer.parseInt(key), convertedValue);
                      }
                  catch (IllegalArgumentException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath +
                              propertyName,oldValue, pv.getValue());
                      throw new TypeMismatchException(pce, requiredType, ex);
                  }
                  catch (IllegalStateException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath +
                              propertyName, oldValue, pv.getValue());
                      throw new ConversionNotSupportedException(pce, requiredType, ex);
                  }
                  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);
                  Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(
                              pd.getReadMethod(), tokens.keys.length);
                  List list = (List) propValue;
                  int index = Integer.parseInt(key);
                  Object oldValue = null;
                  if (isExtractOldValueForEditor() && index < list.size()) {
                      oldValue = list.get(index);
                  }
                  try {
                      Object convertedValue = this.typeConverterDelegate.
                      convertIfNecessary(
                                    propertyName, oldValue, pv.getValue(), requiredType);
                      iflt@span b=1> (indexlt@span b=1> <lt@span b=1> list.size())lt@span b=1> {
                          list.set(index, convertedValue);
                      }
                      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);
                      }
                  }
                  catch (IllegalArgumentException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath
                              + propertyName, oldValue, pv.getValue());
                      throw new TypeMismatchException(pce, requiredType, ex);
                      }
                  } //這里對Map進行注入
                  else if (propValue instanceof Map) {
                      PropertyDescriptor pd = getCachedIntrospectionResults().
                      getPropertyDescriptor(actualName);
                      Class mapKeyType = GenericCollectionTypeResolver.
                      getMapKeyReturnType(
                                    pd.getReadMethod(), tokens.keys.length);
                      Class mapValueType = GenericCollectionTypeResolver.
                      getMapValueReturnType(
                                    pd.getReadMethod(), tokens.keys.length);
                      Map map = (Map) propValue;
                      Object convertedMapKey;
                      Object convertedMapValue;
                      try {
                          convertedMapKey = this.typeConverterDelegate.
                          convertIfNecessary(key, mapKeyType);
                      }
                  catch (IllegalArgumentException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath +
                              propertyName, null, pv.getValue());
                      throw new TypeMismatchException(pce, mapKeyType, ex);
                  }
                  Object oldValue = null;
                  if (isExtractOldValueForEditor()) {
                      oldValue = map.get(convertedMapKey);
                      }
                  trylt@span b=1> {
                      convertedMapValue = this.typeConverterDelegate.convertIfNecessary(
                              propertyName, oldValue, pv.getValue(), mapValueType, null,
                              new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1));
                  }
                  catch (IllegalArgumentException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath +
                              propertyName, oldValue, pv.getValue());
                      throw new TypeMismatchException(pce, mapValueType, ex);
                      }
                      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);
                      if (pd == null || pd.getWriteMethod() == null) {
                              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) {
                                  Method readMethod = pd.getReadMethod();
                                    if (!Modifier.isPublic(readMethod.
                                    getDeclaringClass().getModifiers())) {
                                    readMethod.setAccessible(true);
                              }
                              try {
                                    oldValue = readMethod.invoke(this.object);
                              }
                              catch (Exception ex) {
                                  iflt@span b=1> (logger.isDebugEnabled())lt@span b=1> {
                                      logger.debug("Could not read previous value of property '" +
                                              this.nestedPath + propertyName + "'", ex);
                                    }
                                }
                              }
                              valueToApply = this.typeConverterDelegate.convertIfNecessary
                              (oldValue, originalValue, pd);
                              }
                              pv.getOriginalPropertyValue().conversionNecessary = (valueToApply !=
                              originalValue);
                      }
                      //這里取得注入屬性的set方法,通過反射機制,把對象注入進去
                      Method writeMethod = pd.getWriteMethod();
                      if (!Modifier.isPublic(writeMethod.getDeclaringClass().
                              getModifiers())) {
                              writeMethod.setAccessible(true);
                      }
                      writeMethod.invoke(this.object, valueToApply);
                  }
                  catch (InvocationTargetException ex) {
                      PropertyChangeEvent propertyChangeEvent =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath +
                              propertyName, oldValue, pv.getValue());
                      if (ex.getTargetException() instanceof ClassCastException) {
                              throw new TypeMismatchException(propertyChange
                              Event, pd.getPropertyType(),ex.getTargetException());
                      }
                      else {
                              throw new MethodInvocationException(propertyChangeEvent, ex.
                              getTargetException());
                      }
                  }
                  catch (IllegalArgumentException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath +
                              propertyName, oldValue, pv.getValue());
                      throw new TypeMismatchException(pce, pd.getPropertyType(), ex);
                  }
                  catch (IllegalStateException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath +
                              propertyName, oldValue, pv.getValue());
                      throw new ConversionNotSupportedException(pce, pd.getPropertyType(), ex);
                  }
                  catch (IllegalAccessException ex) {
                      PropertyChangeEvent pce =
                              new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName,
                              oldValue, pv.getValue());
                      throw new MethodInvocationException(pce, ex);
                  }
            }
        }

這樣就完成了對各種Bean屬性的依賴注入過程。從代碼實現細節上看,對比Spring 2.0的源代碼實現,Spring 3.0的源代碼已經有了很大的改進,整個過程更為清晰了,特別是關于依賴注入的部分。如果讀者有興趣,可以比較一下Spring 2.0和Spring 3.0關于依賴注入部分的代碼實現,這樣可以更清晰地看到Spring源代碼的演進過程,也可以看到Spring團隊對代碼進行重構的思路。

在Bean的創建和對象依賴注入的過程中,需要依據BeanDefinition中的信息來遞歸地完成依賴注入。從上面的幾個遞歸過程中可以看到,這些遞歸都是以getBean為入口的。一個遞歸是在上下文體系中查找需要的Bean和創建Bean的遞歸調用;另一個遞歸是在依賴注入時,通過遞歸調用容器的getBean方法,得到當前Bean的依賴Bean,同時也觸發對依賴Bean的創建和注入。在對Bean的屬性進行依賴注入時,解析的過程也是一個遞歸的過程。這樣,根據依賴關系,一層一層地完成Bean的創建和注入,直到最后完成當前Bean的創建。有了這個頂層Bean的創建和對它的屬性依賴注入的完成,意味著和當前Bean相關的整個依賴鏈的注入也完成了。

在Bean創建和依賴注入完成以后,在IoC容器中建立起一系列依靠依賴關系聯系起來的Bean,這個Bean已經不是簡單的Java對象了。該Bean系列以及Bean之間的依賴關系建立完成以后,通過IoC容器的相關接口方法,就可以非常方便地供上層應用使用了。繼續以水桶為例,到這里,我們不但找到了水源,而且成功地把水裝到了水桶中,同時對水桶里的水完成了一系列的處理,比如消毒、煮沸??盡管還是水,但經過一系列的處理以后,這些水已經是開水了,可以直接飲用了。

主站蜘蛛池模板: 保康县| 平舆县| 鲁山县| 永川市| 庄浪县| 兴仁县| 沙雅县| 麻阳| 晋州市| 玉龙| 定州市| 西宁市| 搜索| 龙州县| 营口市| 仁布县| 阳信县| 慈溪市| 张家川| 周至县| 星子县| 平果县| 宝丰县| 凤冈县| 抚宁县| 安丘市| 多伦县| 望都县| 沂源县| 张家界市| 石楼县| 荥经县| 棋牌| 桐乡市| 厦门市| 肇庆市| 白城市| 施甸县| 治多县| 克拉玛依市| 仪陇县|