- Spring技術內幕:深入解析Spring架構與設計原理(第2版)
- 計文柯
- 5629字
- 2018-12-31 19:55:40
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的生產結果, BeanFactory和FactoryBean的區別已經在前面講過,這個過程在后 面還會詳細地分析*/ 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中調用ObjectFactory的createBean*/ //下面會進入到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> &<@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() }); //使用CGLIB的create生成實例化的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的名字或者類型, //來完成Bean的autowire 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; } //注意這個BeanDefinitionValueResolver對BeanDefinition的解析是在 //這個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); } } //下面看一下對其他類型的屬性進行注入的例子,比如array和list 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容器的相關接口方法,就可以非常方便地供上層應用使用了。繼續以水桶為例,到這里,我們不但找到了水源,而且成功地把水裝到了水桶中,同時對水桶里的水完成了一系列的處理,比如消毒、煮沸??盡管還是水,但經過一系列的處理以后,這些水已經是開水了,可以直接飲用了。
- 復雜軟件設計之道:領域驅動設計全面解析與實戰
- Python數據分析基礎
- Learning Data Mining with Python
- 我的第一本算法書
- INSTANT Weka How-to
- Java Web基礎與實例教程
- Nginx Essentials
- PHP+MySQL網站開發項目式教程
- C程序設計案例教程
- 精通Python設計模式(第2版)
- Python High Performance Programming
- 從Excel到Python數據分析:Pandas、xlwings、openpyxl、Matplotlib的交互與應用
- Simulation for Data Science with R
- 計算機應用基礎(第二版)
- Python編程快速上手2