Spring源码解析 依赖注入

来源:互联网 发布:剑桥倚天屠龙史 知乎 编辑:程序博客网 时间:2024/05/17 00:59

当IoC容器的初始化完毕后,我们就要接触IoC容器的核心功能:依赖注入

在基本的IoC容器接口BeanFactory中,有一个getBean的接口方法的定义,这个接口的实现就是触发依赖注入发生的地方。我们从DefaultListableBeanFactory的基类AbstractBeanFactory入手了解getBean()的实现:

 

Java代码  收藏代码
  1. public Object getBean(String name) throws BeansException {  
  2.         return doGetBean(name, nullnullfalse);  
  3.     }  

 这里的getBean接口方法最终通过调用doGetBean来实现的,也就是触发依赖注入发生的地方。

 

 

 

Java代码  收藏代码
  1. protected <T> T doGetBean(  
  2.             final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)  
  3.             throws BeansException {  
  4.   
  5.         final String beanName = transformedBeanName(name);  
  6.         Object bean;  
  7.   
  8.         // Eagerly check singleton cache for manually registered singletons.  
  9.         Object sharedInstance = getSingleton(beanName);  
  10.         if (sharedInstance != null && args == null) {  
  11.             if (logger.isDebugEnabled()) {  
  12.                 if (isSingletonCurrentlyInCreation(beanName)) {  
  13.                     logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +  
  14.                             "' that is not fully initialized yet - a consequence of a circular reference");  
  15.                 }  
  16.                 else {  
  17.                     logger.debug("Returning cached instance of singleton bean '" + beanName + "'");  
  18.                 }  
  19.             }  
  20.             bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);  
  21.         }  
  22.   
  23.         else {  
  24.             // Fail if we're already creating this bean instance:  
  25.             // We're assumably within a circular reference.  
  26.             if (isPrototypeCurrentlyInCreation(beanName)) {  
  27.                 throw new BeanCurrentlyInCreationException(beanName);  
  28.             }  
  29.   
  30.             // Check if bean definition exists in this factory.  
  31.             BeanFactory parentBeanFactory = getParentBeanFactory();  
  32.             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {  
  33.                 // Not found -> check parent.  
  34.                 String nameToLookup = originalBeanName(name);  
  35.                 if (args != null) {  
  36.                     // Delegation to parent with explicit args.  
  37.                     return (T) parentBeanFactory.getBean(nameToLookup, args);  
  38.                 }  
  39.                 else {  
  40.                     // No args -> delegate to standard getBean method.  
  41.                     return parentBeanFactory.getBean(nameToLookup, requiredType);  
  42.                 }  
  43.             }  
  44.   
  45.             if (!typeCheckOnly) {  
  46.                 markBeanAsCreated(beanName);  
  47.             }  
  48.   
  49.             final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);  
  50.             checkMergedBeanDefinition(mbd, beanName, args);  
  51.   
  52.             // Guarantee initialization of beans that the current bean depends on.  
  53.             String[] dependsOn = mbd.getDependsOn();  
  54.             if (dependsOn != null) {  
  55.                 for (String dependsOnBean : dependsOn) {  
  56.                     getBean(dependsOnBean);  
  57.                     registerDependentBean(dependsOnBean, beanName);  
  58.                 }  
  59.             }  
  60.   
  61.             // Create bean instance.  
  62.             if (mbd.isSingleton()) {  
  63.                 sharedInstance = getSingleton(beanName, new ObjectFactory() {  
  64.                     public Object getObject() throws BeansException {  
  65.                         try {  
  66.                             return createBean(beanName, mbd, args);  
  67.                         }  
  68.                         catch (BeansException ex) {  
  69.                             // Explicitly remove instance from singleton cache: It might have been put there  
  70.                             // eagerly by the creation process, to allow for circular reference resolution.  
  71.                             // Also remove any beans that received a temporary reference to the bean.  
  72.                             destroySingleton(beanName);  
  73.                             throw ex;  
  74.                         }  
  75.                     }  
  76.                 });  
  77.                 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);  
  78.             }  
  79.   
  80.             else if (mbd.isPrototype()) {  
  81.                 // It's a prototype -> create a new instance.  
  82.                 Object prototypeInstance = null;  
  83.                 try {  
  84.                     beforePrototypeCreation(beanName);  
  85.                     prototypeInstance = createBean(beanName, mbd, args);  
  86.                 }  
  87.                 finally {  
  88.                     afterPrototypeCreation(beanName);  
  89.                 }  
  90.                 bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);  
  91.             }  
  92.   
  93.             else {  
  94.                 String scopeName = mbd.getScope();  
  95.                 final Scope scope = this.scopes.get(scopeName);  
  96.                 if (scope == null) {  
  97.                     throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");  
  98.                 }  
  99.                 try {  
  100.                     Object scopedInstance = scope.get(beanName, new ObjectFactory() {  
  101.                         public Object getObject() throws BeansException {  
  102.                             beforePrototypeCreation(beanName);  
  103.                             try {  
  104.                                 return createBean(beanName, mbd, args);  
  105.                             }  
  106.                             finally {  
  107.                                 afterPrototypeCreation(beanName);  
  108.                             }  
  109.                         }  
  110.                     });  
  111.                     bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);  
  112.                 }  
  113.                 catch (IllegalStateException ex) {  
  114.                     throw new BeanCreationException(beanName,  
  115.                             "Scope '" + scopeName + "' is not active for the current thread; " +  
  116.                             "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",  
  117.                             ex);  
  118.                 }  
  119.             }  
  120.         }  
  121.   
  122.         // Check if required type matches the type of the actual bean instance.  
  123.         if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {  
  124.             throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());  
  125.         }  
  126.         return (T) bean;  
  127.     }  

 首先从缓存中取,处理已经被创建过的单件模式的bean,对这种bean的请求不需要重复地创建,接着

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null)主要完成的是判断它是一个FactoryBean还是普通的Bean对象,如果是普通的Bean对象则直接返回,如果是FactoryBean,则创建一个新的对象Bean返回,具体详细的步骤就不讲了,接着检查IoC容器里的BeanDefinition,看是否取得我们需要的Bean.如果在当前俄工厂中取不到,则到双亲BeanFactory中去取,如果当前的双亲工厂娶不到,那就顺着双亲BeanFactory链一直向上寻找。final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)根据beanName获取到BeanDefinition。

String[] dependsOn = mbd.getDependsOn() 取得当前bean的所有依赖Bean,这样会触发getBean的递归调用,直至渠道一个没有任何依赖的bean为止。

 

接着就是创建Bean的实例,首先它判断的Bean的生命周期,然后才调用createBean创建Bean的实例。然后对创建出来的Bean进行类型检查,这里的bean已经是包含依赖关系的Bean.

Java代码  收藏代码
  1. protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)  
  2.             throws BeanCreationException {  
  3.   
  4.         if (logger.isDebugEnabled()) {  
  5.             logger.debug("Creating instance of bean '" + beanName + "'");  
  6.         }  
  7.         // Make sure bean class is actually resolved at this point.  
  8.         resolveBeanClass(mbd, beanName);  
  9.   
  10.         // Prepare method overrides.  
  11.         try {  
  12.             mbd.prepareMethodOverrides();  
  13.         }  
  14.         catch (BeanDefinitionValidationException ex) {  
  15.             throw new BeanDefinitionStoreException(mbd.getResourceDescription(),  
  16.                     beanName, "Validation of method overrides failed", ex);  
  17.         }  
  18.   
  19.         try {  
  20.             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.  
  21.             Object bean = resolveBeforeInstantiation(beanName, mbd);  
  22.             if (bean != null) {  
  23.                 return bean;  
  24.             }  
  25.         }  
  26.         catch (Throwable ex) {  
  27.             throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  28.                     "BeanPostProcessor before instantiation of bean failed", ex);  
  29.         }  
  30.   
  31.         Object beanInstance = doCreateBean(beanName, mbd, args);  
  32.         if (logger.isDebugEnabled()) {  
  33.             logger.debug("Finished creating instance of bean '" + beanName + "'");  
  34.         }  
  35.         return beanInstance;  
  36.     }  

 

resolveBeanClass(mbd, beanName);

首先判断需要创建的bean是否可以被实例化,这个类是否可以通过类装载器来载入。

Object bean = resolveBeforeInstantiation(beanName, mbd);

接着如果bean配置了PostProcessor,那么这里返回的是一个代理

Object beanInstance = doCreateBean(beanName, mbd, args);
这里是创建bean的调用.

Java代码  收藏代码
  1. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {  
  2.         // Instantiate the bean.  
  3.         BeanWrapper instanceWrapper = null;  
  4.         if (mbd.isSingleton()) {  
  5.             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);  
  6.         }  
  7.         if (instanceWrapper == null) {  
  8.             instanceWrapper = createBeanInstance(beanName, mbd, args);  
  9.         }  
  10.         final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);  
  11.         Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);  
  12.   
  13.         // Allow post-processors to modify the merged bean definition.  
  14.         synchronized (mbd.postProcessingLock) {  
  15.             if (!mbd.postProcessed) {  
  16.                 applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);  
  17.                 mbd.postProcessed = true;  
  18.             }  
  19.         }  
  20.   
  21.         // Eagerly cache singletons to be able to resolve circular references  
  22.         // even when triggered by lifecycle interfaces like BeanFactoryAware.  
  23.         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&  
  24.                 isSingletonCurrentlyInCreation(beanName));  
  25.         if (earlySingletonExposure) {  
  26.             if (logger.isDebugEnabled()) {  
  27.                 logger.debug("Eagerly caching bean '" + beanName +  
  28.                         "' to allow for resolving potential circular references");  
  29.             }  
  30.             addSingletonFactory(beanName, new ObjectFactory() {  
  31.                 public Object getObject() throws BeansException {  
  32.                     return getEarlyBeanReference(beanName, mbd, bean);  
  33.                 }  
  34.             });  
  35.         }  
  36.   
  37.         // Initialize the bean instance.  
  38.         Object exposedObject = bean;  
  39.         try {  
  40.             populateBean(beanName, mbd, instanceWrapper);  
  41.             if (exposedObject != null) {  
  42.                 exposedObject = initializeBean(beanName, exposedObject, mbd);  
  43.             }  
  44.         }  
  45.         catch (Throwable ex) {  
  46.             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
  47.                 throw (BeanCreationException) ex;  
  48.             }  
  49.             else {  
  50.                 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);  
  51.             }  
  52.         }  
  53.   
  54.         if (earlySingletonExposure) {  
  55.             Object earlySingletonReference = getSingleton(beanName, false);  
  56.             if (earlySingletonReference != null) {  
  57.                 if (exposedObject == bean) {  
  58.                     exposedObject = earlySingletonReference;  
  59.                 }  
  60.                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
  61.                     String[] dependentBeans = getDependentBeans(beanName);  
  62.                     Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);  
  63.                     for (String dependentBean : dependentBeans) {  
  64.                         if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
  65.                             actualDependentBeans.add(dependentBean);  
  66.                         }  
  67.                     }  
  68.                     if (!actualDependentBeans.isEmpty()) {  
  69.                         throw new BeanCurrentlyInCreationException(beanName,  
  70.                                 "Bean with name '" + beanName + "' has been injected into other beans [" +  
  71.                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
  72.                                 "] in its raw version as part of a circular reference, but has eventually been " +  
  73.                                 "wrapped. This means that said other beans do not use the final version of the " +  
  74.                                 "bean. This is often the result of over-eager type matching - consider using " +  
  75.                                 "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  
  76.                     }  
  77.                 }  
  78.             }  
  79.         }  
  80.   
  81.         // Register bean as disposable.  
  82.         try {  
  83.             registerDisposableBeanIfNecessary(beanName, bean, mbd);  
  84.         }  
  85.         catch (BeanDefinitionValidationException ex) {  
  86.             throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);  
  87.         }  
  88.   
  89.         return exposedObject;  
  90.     }  

 BeanWrapper是用来持有创建出来的bean对象的。如果是singleton,先把缓存中的同名bean清除。如果bean首次创建,那么缓存中没有bean的实例,即进入到创建bean.

instanceWrapper = createBeanInstance(beanName, mbd, args);

Java代码  收藏代码
  1. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {  
  2.     // Make sure bean class is actually resolved at this point.  
  3.     Class beanClass = resolveBeanClass(mbd, beanName);  
  4.   
  5.     if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {  
  6.         throw new BeanCreationException(mbd.getResourceDescription(), beanName,  
  7.                 "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());  
  8.     }  
  9.   
  10.     if (mbd.getFactoryMethodName() != null)  {  
  11.         return instantiateUsingFactoryMethod(beanName, mbd, args);  
  12.     }  
  13.   
  14.     // Shortcut when re-creating the same bean...  
  15.     boolean resolved = false;  
  16.     boolean autowireNecessary = false;  
  17.     if (args == null) {  
  18.         synchronized (mbd.constructorArgumentLock) {  
  19.             if (mbd.resolvedConstructorOrFactoryMethod != null) {  
  20.                 resolved = true;  
  21.                 autowireNecessary = mbd.constructorArgumentsResolved;  
  22.             }  
  23.         }  
  24.     }  
  25.     if (resolved) {  
  26.         if (autowireNecessary) {  
  27.             return autowireConstructor(beanName, mbd, nullnull);  
  28.         }  
  29.         else {  
  30.             return instantiateBean(beanName, mbd);  
  31.         }  
  32.     }  
  33.   
  34.     // Need to determine the constructor...  
  35.     Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  
  36.     if (ctors != null ||  
  37.             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||  
  38.             mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {  
  39.         return autowireConstructor(beanName, mbd, ctors, args);  
  40.     }  
  41.   
  42.     // No special handling: simply use no-arg constructor.  
  43.     return instantiateBean(beanName, mbd);  
  44. }  

 

这里包含使用工厂方法对Bean进行实例化;使用构造函数对Bean进行实例化;使用默认额构造函数对Bean进行实例化,我们接下来看看最常见的实例化过程instantiateBean:

Java代码  收藏代码
  1. protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {  
  2.         try {  
  3.             Object beanInstance;  
  4.             final BeanFactory parent = this;  
  5.             if (System.getSecurityManager() != null) {  
  6.                 beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {  
  7.                     public Object run() {  
  8.                         return getInstantiationStrategy().instantiate(mbd, beanName, parent);  
  9.                     }  
  10.                 }, getAccessControlContext());  
  11.             }  
  12.             else {  
  13.                 beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);  
  14.             }  
  15.             BeanWrapper bw = new BeanWrapperImpl(beanInstance);  
  16.             initBeanWrapper(bw);  
  17.             return bw;  
  18.         }  
  19.         catch (Throwable ex) {  
  20.             throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
  21.         }  
  22.     }  

 这里我们使用默认的实例化策略对Bean进行实例化,默认的实例化策略是

CglibSubclassingInstantiationStrategy,也就是用cglib来对bean

进行实例化。

<!--EndFragment-->

首先取得在BeanFactory中设置的property的值,这些值来自对BeanDefinition的解析。接着开始进行依赖注入的过程,先处理autowire的注入接着对属性进行注入。接下来我们看看具体对属性进行解析和注入的过程。

Java代码  收藏代码
  1. protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {  
  2.         if (pvs == null || pvs.isEmpty()) {  
  3.             return;  
  4.         }  
  5.   
  6.         MutablePropertyValues mpvs = null;  
  7.         List<PropertyValue> original;  
  8.           
  9.         if (System.getSecurityManager()!= null) {  
  10.             if (bw instanceof BeanWrapperImpl) {  
  11.                 ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());  
  12.             }  
  13.         }  
  14.   
  15.         if (pvs instanceof MutablePropertyValues) {  
  16.             mpvs = (MutablePropertyValues) pvs;  
  17.             if (mpvs.isConverted()) {  
  18.                 // Shortcut: use the pre-converted values as-is.  
  19.                 try {  
  20.                     bw.setPropertyValues(mpvs);  
  21.                     return;  
  22.                 }  
  23.                 catch (BeansException ex) {  
  24.                     throw new BeanCreationException(  
  25.                             mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
  26.                 }  
  27.             }  
  28.             original = mpvs.getPropertyValueList();  
  29.         }  
  30.         else {  
  31.             original = Arrays.asList(pvs.getPropertyValues());  
  32.         }  
  33.   
  34.         TypeConverter converter = getCustomTypeConverter();  
  35.         if (converter == null) {  
  36.             converter = bw;  
  37.         }  
  38.         BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);  
  39.   
  40.         // Create a deep copy, resolving any references for values.  
  41.         List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());  
  42.         boolean resolveNecessary = false;  
  43.         for (PropertyValue pv : original) {  
  44.             if (pv.isConverted()) {  
  45.                 deepCopy.add(pv);  
  46.             }  
  47.             else {  
  48.                 String propertyName = pv.getName();  
  49.                 Object originalValue = pv.getValue();  
  50.                 Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);  
  51.                 Object convertedValue = resolvedValue;  
  52.                 boolean convertible = bw.isWritableProperty(propertyName) &&  
  53.                         !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);  
  54.                 if (convertible) {  
  55.                     convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);  
  56.                 }  
  57.                 // Possibly store converted value in merged bean definition,  
  58.                 // in order to avoid re-conversion for every created bean instance.  
  59.                 if (resolvedValue == originalValue) {  
  60.                     if (convertible) {  
  61.                         pv.setConvertedValue(convertedValue);  
  62.                     }  
  63.                     deepCopy.add(pv);  
  64.                 }  
  65.                 else if (convertible && originalValue instanceof TypedStringValue &&  
  66.                         !((TypedStringValue) originalValue).isDynamic() &&  
  67.                         !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {  
  68.                     pv.setConvertedValue(convertedValue);  
  69.                     deepCopy.add(pv);  
  70.                 }  
  71.                 else {  
  72.                     resolveNecessary = true;  
  73.                     deepCopy.add(new PropertyValue(pv, convertedValue));  
  74.                 }  
  75.             }  
  76.         }  
  77.         if (mpvs != null && !resolveNecessary) {  
  78.             mpvs.setConverted();  
  79.         }  
  80.   
  81.         // Set our (possibly massaged) deep copy.  
  82.         try {  
  83.             bw.setPropertyValues(new MutablePropertyValues(deepCopy));  
  84.         }  
  85.         catch (BeansException ex) {  
  86.             throw new BeanCreationException(  
  87.                     mbd.getResourceDescription(), beanName, "Error setting property values", ex);  
  88.         }  
  89.     }  

 

 首先为解析值创建一个拷贝,拷贝的数据将会被注入到Bean中,最后设置到BeanWrapper中。

 

Java代码  收藏代码
  1. public Object resolveValueIfNecessary(Object argName, Object value) {  
  2.         // We must check each value to see whether it requires a runtime reference  
  3.         // to another bean to be resolved.  
  4.         if (value instanceof RuntimeBeanReference) {  
  5.             RuntimeBeanReference ref = (RuntimeBeanReference) value;  
  6.             return resolveReference(argName, ref);  
  7.         }  
  8.         else if (value instanceof RuntimeBeanNameReference) {  
  9.             String refName = ((RuntimeBeanNameReference) value).getBeanName();  
  10.             refName = String.valueOf(evaluate(refName));  
  11.             if (!this.beanFactory.containsBean(refName)) {  
  12.                 throw new BeanDefinitionStoreException(  
  13.                         "Invalid bean name '" + refName + "' in bean reference for " + argName);  
  14.             }  
  15.             return refName;  
  16.         }  
  17.         else if (value instanceof BeanDefinitionHolder) {  
  18.             // Resolve BeanDefinitionHolder: contains BeanDefinition with name and aliases.  
  19.             BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) value;  
  20.             return resolveInnerBean(argName, bdHolder.getBeanName(), bdHolder.getBeanDefinition());  
  21.         }  
  22.         else if (value instanceof BeanDefinition) {  
  23.             // Resolve plain BeanDefinition, without contained name: use dummy name.  
  24.             BeanDefinition bd = (BeanDefinition) value;  
  25.             return resolveInnerBean(argName, "(inner bean)", bd);  
  26.         }  
  27.         else if (value instanceof ManagedArray) {  
  28.             // May need to resolve contained runtime references.  
  29.             ManagedArray array = (ManagedArray) value;  
  30.             Class elementType = array.resolvedElementType;  
  31.             if (elementType == null) {  
  32.                 String elementTypeName = array.getElementTypeName();  
  33.                 if (StringUtils.hasText(elementTypeName)) {  
  34.                     try {  
  35.                         elementType = ClassUtils.forName(elementTypeName, this.beanFactory.getBeanClassLoader());  
  36.                         array.resolvedElementType = elementType;  
  37.                     }  
  38.                     catch (Throwable ex) {  
  39.                         // Improve the message by showing the context.  
  40.                         throw new BeanCreationException(  
  41.                                 this.beanDefinition.getResourceDescription(), this.beanName,  
  42.                                 "Error resolving array type for " + argName, ex);  
  43.                     }  
  44.                 }  
  45.                 else {  
  46.                     elementType = Object.class;  
  47.                 }  
  48.             }  
  49.             return resolveManagedArray(argName, (List<?>) value, elementType);  
  50.         }  
  51.         else if (value instanceof ManagedList) {  
  52.             // May need to resolve contained runtime references.  
  53.             return resolveManagedList(argName, (List<?>) value);  
  54.         }  
  55.         else if (value instanceof ManagedSet) {  
  56.             // May need to resolve contained runtime references.  
  57.             return resolveManagedSet(argName, (Set<?>) value);  
  58.         }  
  59.         else if (value instanceof ManagedMap) {  
  60.             // May need to resolve contained runtime references.  
  61.             return resolveManagedMap(argName, (Map<?, ?>) value);  
  62.         }  
  63.         else if (value instanceof ManagedProperties) {  
  64.             Properties original = (Properties) value;  
  65.             Properties copy = new Properties();  
  66.             for (Map.Entry propEntry : original.entrySet()) {  
  67.                 Object propKey = propEntry.getKey();  
  68.                 Object propValue = propEntry.getValue();  
  69.                 if (propKey instanceof TypedStringValue) {  
  70.                     propKey = evaluate((TypedStringValue) propKey);  
  71.                 }  
  72.                 if (propValue instanceof TypedStringValue) {  
  73.                     propValue = evaluate((TypedStringValue) propValue);  
  74.                 }  
  75.                 copy.put(propKey, propValue);  
  76.             }  
  77.             return copy;  
  78.         }  
  79.         else if (value instanceof TypedStringValue) {  
  80.             // Convert value to target type here.  
  81.             TypedStringValue typedStringValue = (TypedStringValue) value;  
  82.             Object valueObject = evaluate(typedStringValue);  
  83.             try {  
  84.                 Class<?> resolvedTargetType = resolveTargetType(typedStringValue);  
  85.                 if (resolvedTargetType != null) {  
  86.                     return this.typeConverter.convertIfNecessary(valueObject, resolvedTargetType);  
  87.                 }  
  88.                 else {  
  89.                     return valueObject;  
  90.                 }  
  91.             }  
  92.             catch (Throwable ex) {  
  93.                 // Improve the message by showing the context.  
  94.                 throw new BeanCreationException(  
  95.                         this.beanDefinition.getResourceDescription(), this.beanName,  
  96.                         "Error converting typed String value for " + argName, ex);  
  97.             }  
  98.         }  
  99.         else {  
  100.             return evaluate(value);  
  101.         }  
  102.     }  

 

 这个函数里定义了对各种类型属性的解析而真正的注入是在BeanWrapperImpl类中的setPropertyValue方法中:

 

Java代码  收藏代码
  1. private void setPropertyValue(PropertyTokenHolder tokens, PropertyValue pv) throws BeansException {  
  2.         String propertyName = tokens.canonicalName;  
  3.         String actualName = tokens.actualName;  
  4.   
  5.         if (tokens.keys != null) {  
  6.             // Apply indexes and map keys: fetch value for all keys but the last one.  
  7.             PropertyTokenHolder getterTokens = new PropertyTokenHolder();  
  8.             getterTokens.canonicalName = tokens.canonicalName;  
  9.             getterTokens.actualName = tokens.actualName;  
  10.             getterTokens.keys = new String[tokens.keys.length - 1];  
  11.             System.arraycopy(tokens.keys, 0, getterTokens.keys, 0, tokens.keys.length - 1);  
  12.             Object propValue;  
  13.             try {  
  14.                 propValue = getPropertyValue(getterTokens);  
  15.             }  
  16.             catch (NotReadablePropertyException ex) {  
  17.                 throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,  
  18.                         "Cannot access indexed value in property referenced " +  
  19.                         "in indexed property path '" + propertyName + "'", ex);  
  20.             }  
  21.             // Set value for last key.  
  22.             String key = tokens.keys[tokens.keys.length - 1];  
  23.             if (propValue == null) {  
  24.                 throw new NullValueInNestedPathException(getRootClass(), this.nestedPath + propertyName,  
  25.                         "Cannot access indexed value in property referenced " +  
  26.                         "in indexed property path '" + propertyName + "': returned null");  
  27.             }  
  28.             else if (propValue.getClass().isArray()) {  
  29.                 PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
  30.                 Class requiredType = propValue.getClass().getComponentType();  
  31.                 int arrayIndex = Integer.parseInt(key);  
  32.                 Object oldValue = null;  
  33.                 try {  
  34.                     if (isExtractOldValueForEditor()) {  
  35.                         oldValue = Array.get(propValue, arrayIndex);  
  36.                     }  
  37.                     Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,  
  38.                             new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));  
  39.                     Array.set(propValue, arrayIndex, convertedValue);  
  40.                 }  
  41.                 catch (IndexOutOfBoundsException ex) {  
  42.                     throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,  
  43.                             "Invalid array index in property path '" + propertyName + "'", ex);  
  44.                 }  
  45.             }  
  46.             else if (propValue instanceof List) {  
  47.                 PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
  48.                 Class requiredType = GenericCollectionTypeResolver.getCollectionReturnType(  
  49.                         pd.getReadMethod(), tokens.keys.length);  
  50.                 List list = (List) propValue;  
  51.                 int index = Integer.parseInt(key);  
  52.                 Object oldValue = null;  
  53.                 if (isExtractOldValueForEditor() && index < list.size()) {  
  54.                     oldValue = list.get(index);  
  55.                 }  
  56.                 Object convertedValue = convertIfNecessary(propertyName, oldValue, pv.getValue(), requiredType,  
  57.                         new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), requiredType));  
  58.                 if (index < list.size()) {  
  59.                     list.set(index, convertedValue);  
  60.                 }  
  61.                 else if (index >= list.size()) {  
  62.                     for (int i = list.size(); i < index; i++) {  
  63.                         try {  
  64.                             list.add(null);  
  65.                         }  
  66.                         catch (NullPointerException ex) {  
  67.                             throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,  
  68.                                     "Cannot set element with index " + index + " in List of size " +  
  69.                                     list.size() + ", accessed using property path '" + propertyName +  
  70.                                     "': List does not support filling up gaps with null elements");  
  71.                         }  
  72.                     }  
  73.                     list.add(convertedValue);  
  74.                 }  
  75.             }  
  76.             else if (propValue instanceof Map) {  
  77.                 PropertyDescriptor pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
  78.                 Class mapKeyType = GenericCollectionTypeResolver.getMapKeyReturnType(  
  79.                         pd.getReadMethod(), tokens.keys.length);  
  80.                 Class mapValueType = GenericCollectionTypeResolver.getMapValueReturnType(  
  81.                         pd.getReadMethod(), tokens.keys.length);  
  82.                 Map map = (Map) propValue;  
  83.                 // IMPORTANT: Do not pass full property name in here - property editors  
  84.                 // must not kick in for map keys but rather only for map values.  
  85.                 Object convertedMapKey = convertIfNecessary(nullnull, key, mapKeyType,  
  86.                         new PropertyTypeDescriptor(pd, new MethodParameter(pd.getReadMethod(), -1), mapKeyType));  
  87.                 Object oldValue = null;  
  88.                 if (isExtractOldValueForEditor()) {  
  89.                     oldValue = map.get(convertedMapKey);  
  90.                 }  
  91.                 // Pass full property name and old value in here, since we want full  
  92.                 // conversion ability for map values.  
  93.                 Object convertedMapValue = convertIfNecessary(  
  94.                         propertyName, oldValue, pv.getValue(), mapValueType,  
  95.                         new TypeDescriptor(new MethodParameter(pd.getReadMethod(), -1, tokens.keys.length + 1)));  
  96.                 map.put(convertedMapKey, convertedMapValue);  
  97.             }  
  98.             else {  
  99.                 throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,  
  100.                         "Property referenced in indexed property path '" + propertyName +  
  101.                         "' is neither an array nor a List nor a Map; returned value was [" + pv.getValue() + "]");  
  102.             }  
  103.         }  
  104.   
  105.         else {  
  106.             PropertyDescriptor pd = pv.resolvedDescriptor;  
  107.             if (pd == null || !pd.getWriteMethod().getDeclaringClass().isInstance(this.object)) {  
  108.                 pd = getCachedIntrospectionResults().getPropertyDescriptor(actualName);  
  109.                 if (pd == null || pd.getWriteMethod() == null) {  
  110.                     if (pv.isOptional()) {  
  111.                         logger.debug("Ignoring optional value for property '" + actualName +  
  112.                                 "' - property not found on bean class [" + getRootClass().getName() + "]");  
  113.                         return;  
  114.                     }  
  115.                     else {  
  116.                         PropertyMatches matches = PropertyMatches.forProperty(propertyName, getRootClass());  
  117.                         throw new NotWritablePropertyException(  
  118.                                 getRootClass(), this.nestedPath + propertyName,  
  119.                                 matches.buildErrorMessage(), matches.getPossibleMatches());  
  120.                     }  
  121.                 }  
  122.                 pv.getOriginalPropertyValue().resolvedDescriptor = pd;  
  123.             }  
  124.   
  125.             Object oldValue = null;  
  126.             try {  
  127.                 Object originalValue = pv.getValue();  
  128.                 Object valueToApply = originalValue;  
  129.                 if (!Boolean.FALSE.equals(pv.conversionNecessary)) {  
  130.                     if (pv.isConverted()) {  
  131.                         valueToApply = pv.getConvertedValue();  
  132.                     }  
  133.                     else {  
  134.                         if (isExtractOldValueForEditor() && pd.getReadMethod() != null) {  
  135.                             final Method readMethod = pd.getReadMethod();  
  136.                             if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()) &&  
  137.                                     !readMethod.isAccessible()) {  
  138.                                 if (System.getSecurityManager()!= null) {  
  139.                                     AccessController.doPrivileged(new PrivilegedAction<Object>() {  
  140.                                         public Object run() {  
  141.                                             readMethod.setAccessible(true);  
  142.                                             return null;  
  143.                                         }  
  144.                                     });  
  145.                                 }  
  146.                                 else {  
  147.                                     readMethod.setAccessible(true);  
  148.                                 }  
  149.                             }  
  150.                             try {  
  151.                                 if (System.getSecurityManager() != null) {  
  152.                                     oldValue = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
  153.                                         public Object run() throws Exception {  
  154.                                             return readMethod.invoke(object);  
  155.                                         }  
  156.                                     }, acc);  
  157.                                 }  
  158.                                 else {  
  159.                                     oldValue = readMethod.invoke(object);  
  160.                                 }  
  161.                             }  
  162.                             catch (Exception ex) {  
  163.                                 if (ex instanceof PrivilegedActionException) {  
  164.                                     ex = ((PrivilegedActionException) ex).getException();  
  165.                                 }  
  166.                                 if (logger.isDebugEnabled()) {  
  167.                                     logger.debug("Could not read previous value of property '" +  
  168.                                             this.nestedPath + propertyName + "'", ex);  
  169.                                 }  
  170.                             }  
  171.                         }  
  172.                         valueToApply = convertForProperty(propertyName, oldValue, originalValue, pd);  
  173.                     }  
  174.                     pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);  
  175.                 }  
  176.                 final Method writeMethod = (pd instanceof GenericTypeAwarePropertyDescriptor ?  
  177.                         ((GenericTypeAwarePropertyDescriptor) pd).getWriteMethodForActualAccess() :  
  178.                         pd.getWriteMethod());  
  179.                 if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {  
  180.                     if (System.getSecurityManager()!= null) {  
  181.                         AccessController.doPrivileged(new PrivilegedAction<Object>() {  
  182.                             public Object run() {  
  183.                                 writeMethod.setAccessible(true);  
  184.                                 return null;  
  185.                             }  
  186.                         });  
  187.                     }  
  188.                     else {  
  189.                         writeMethod.setAccessible(true);  
  190.                     }  
  191.                 }  
  192.                 final Object value = valueToApply;  
  193.                 if (System.getSecurityManager() != null) {  
  194.                     try {  
  195.                         AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {  
  196.                             public Object run() throws Exception {  
  197.                                 writeMethod.invoke(object, value);  
  198.                                 return null;  
  199.                             }  
  200.                         }, acc);  
  201.                     }  
  202.                     catch (PrivilegedActionException ex) {  
  203.                         throw ex.getException();  
  204.                     }  
  205.                 }  
  206.                 else {  
  207.                     writeMethod.invoke(this.object, value);  
  208.                 }  
  209.             }  
  210.             catch (TypeMismatchException ex) {  
  211.                 throw ex;  
  212.             }  
  213.             catch (InvocationTargetException ex) {  
  214.                 PropertyChangeEvent propertyChangeEvent =  
  215.                         new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());  
  216.                 if (ex.getTargetException() instanceof ClassCastException) {  
  217.                     throw new TypeMismatchException(propertyChangeEvent, pd.getPropertyType(), ex.getTargetException());  
  218.                 }  
  219.                 else {  
  220.                     throw new MethodInvocationException(propertyChangeEvent, ex.getTargetException());  
  221.                 }  
  222.             }  
  223.             catch (Exception ex) {  
  224.                 PropertyChangeEvent pce =  
  225.                         new PropertyChangeEvent(this.rootObject, this.nestedPath + propertyName, oldValue, pv.getValue());  
  226.                 throw new MethodInvocationException(pce, ex);  
  227.             }  
  228.         }  
  229.     }  

 

 

 到这里依赖注入已经完成了。


0 0
原创粉丝点击