- Spring技术内幕:深入解析Spring架构与设计原理(第2版)
- 计文柯
- 5629字
- 2025-02-18 01:32:52
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容器的相关接口方法,就可以非常方便地供上层应用使用了。继续以水桶为例,到这里,我们不但找到了水源,而且成功地把水装到了水桶中,同时对水桶里的水完成了一系列的处理,比如消毒、煮沸⋯⋯尽管还是水,但经过一系列的处理以后,这些水已经是开水了,可以直接饮用了。