分享

Spring源码浅析 -- 依赖注入

 开心豆豆2010 2011-11-24


Ioc已经完成了对配置文件的载入和解析,接下来将会完成Ioc容器的核心功能 依赖注入。

在依赖注入之前,还要进行对bean的生成和初始化,生成方式分为两种JDK自身的方式和引入CGLIB类库的方式。

首先就从触发这一系列过程的入口说起,BeanFactroy.getBean

 

1.bean在BeanFactroy中的生成

getBean方法的具体实现是在AbstractBeanFactory中

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

 

它会调用doGetBean方法

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

 这个方法首先处理beanName(transformedBeanName(name)),因为会用&开头的情况,然后会在以前的 singleton缓存中去找需要的bean(getSingleton(beanName)),因为如果是singleton的bean就不用再创建, 然后判断此bean是否在此beanfactory中定义(containsBeanDefinition(beanName)),如果没有递归至双亲 beanfactory,以上条件不满足的话,接下来得到beandefination的定义 (getMergedLocalBeanDefinition(beanName)),开始创建bean,第一步分析此bean的depand-on的情 况,先把它们初始化,第二步判断bean的生命周期,如果是singleton的话,使用对应的singletonFactory来生成,如果是 prototype的,使用createBean(beanName, mbd, args)方法生成。

 

createBean(beanName, mbd, args)方法的具体实现是在AbstractAutowireCapableBeanFactory中实现

 

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

 

除去一些验证工作,创建bean在doCreateBean(beanName, mbd, args)中实现

 

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.         exposedObject = initializeBean(beanName, exposedObject, mbd);  
  42.     }  
  43.     catch (Throwable ex) {  
  44.         if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {  
  45.             throw (BeanCreationException) ex;  
  46.         }  
  47.         else {  
  48.             throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);  
  49.         }  
  50.     }  
  51.   
  52.     if (earlySingletonExposure) {  
  53.         Object earlySingletonReference = getSingleton(beanName, false);  
  54.         if (earlySingletonReference != null) {  
  55.             if (exposedObject == bean) {  
  56.                 exposedObject = earlySingletonReference;  
  57.             }  
  58.             else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {  
  59.                 String[] dependentBeans = getDependentBeans(beanName);  
  60.                 Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);  
  61.                 for (String dependentBean : dependentBeans) {  
  62.                     if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {  
  63.                         actualDependentBeans.add(dependentBean);  
  64.                     }  
  65.                 }  
  66.                 if (!actualDependentBeans.isEmpty()) {  
  67.                     throw new BeanCurrentlyInCreationException(beanName,  
  68.                             "Bean with name '" + beanName + "' has been injected into other beans [" +  
  69.                             StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +  
  70.                             "] in its raw version as part of a circular reference, but has eventually been " +  
  71.                             "wrapped. This means that said other beans do not use the final version of the " +  
  72.                             "bean. This is often the result of over-eager type matching - consider using " +  
  73.                             "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");  
  74.                 }  
  75.             }  
  76.         }  
  77.     }  
  78.   
  79.     // Register bean as disposable.  
  80.     try {  
  81.         registerDisposableBeanIfNecessary(beanName, bean, mbd);  
  82.     }  
  83.     catch (BeanDefinitionValidationException ex) {  
  84.         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);  
  85.     }  
  86.   
  87.     return exposedObject;  
  88. }  

 在此引入一个bean的包装类BeanWrapper,如果是singleton的,先从缓存中取(instanceWrapper = this.factoryBeanInstanceCache.remove(beanName)),如果为null的话 进入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.     if (mbd.resolvedConstructorOrFactoryMethod != null && args == null) {  
  16.         if (mbd.constructorArgumentsResolved) {  
  17.             return autowireConstructor(beanName, mbd, nullnull);  
  18.         }  
  19.         else {  
  20.             return instantiateBean(beanName, mbd);  
  21.         }  
  22.     }  
  23.   
  24.     // Need to determine the constructor...  
  25.     Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);  
  26.     if (ctors != null ||  
  27.             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||  
  28.             mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {  
  29.         return autowireConstructor(beanName, mbd, ctors, args);  
  30.     }  
  31.   
  32.     // No special handling: simply use no-arg constructor.  
  33.     return instantiateBean(beanName, mbd);  
  34. }  

 如果此bean配置了工厂方法(mbd.getFactoryMethodName() != null),则使用工厂类进行bean的创建,如果此bean注入了构造器参数(ctors != null),则使用非默认的构造器对应的方法autowireConstructor进行生成,最后一种情况是最常见的,非工厂类,且使用默认无参的构造 方法,instantiateBean(beanName, mbd)

 

 

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.   
  8.                 public Object run() {  
  9.                     return getInstantiationStrategy().instantiate(mbd, beanName, parent);  
  10.                 }  
  11.             }, getAccessControlContext());  
  12.         }  
  13.         else {  
  14.             beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);  
  15.         }  
  16.           
  17.         BeanWrapper bw = new BeanWrapperImpl(beanInstance);  
  18.         initBeanWrapper(bw);  
  19.         return bw;  
  20.     }  
  21.     catch (Throwable ex) {  
  22.         throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);  
  23.     }  
  24. }  

 在这里首先生成beanInstance对象,然后在对它进行包装(BeanWrapper bw = new BeanWrapperImpl(beanInstance)) 继而完成bean的生成,生成beanInstance 使用getInstantiationStrategy().instantiate(mbd, beanName, parent)方法,在此首先得到InstantiationStrategy的对象,然后进行instantiate,具体实现是在 SimpleInstantiationStrategy类中,

 

Java代码  收藏代码
  1. public Object instantiate(  
  2.         RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {  
  3.   
  4.     // Don't override the class with CGLIB if no overrides.  
  5.     if (beanDefinition.getMethodOverrides().isEmpty()) {  
  6.         Constructor constructorToUse = (Constructor) beanDefinition.resolvedConstructorOrFactoryMethod;  
  7.         if (constructorToUse == null) {  
  8.             final Class clazz = beanDefinition.getBeanClass();  
  9.             if (clazz.isInterface()) {  
  10.                 throw new BeanInstantiationException(clazz, "Specified class is an interface");  
  11.             }  
  12.             try {  
  13.                 if (System.getSecurityManager() != null) {  
  14.                     constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor>() {  
  15.                         public Constructor run() throws Exception {  
  16.                             return clazz.getDeclaredConstructor((Class[]) null);  
  17.                         }  
  18.                     });  
  19.                 } else {  
  20.                     constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);  
  21.                 }  
  22.                 beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;  
  23.             }  
  24.             catch (Exception ex) {  
  25.                 throw new BeanInstantiationException(clazz, "No default constructor found", ex);  
  26.             }  
  27.         }  
  28.         return BeanUtils.instantiateClass(constructorToUse);  
  29.     }  
  30.     else {  
  31.         // Must generate CGLIB subclass.  
  32.         return instantiateWithMethodInjection(beanDefinition, beanName, owner);  
  33.     }  
  34. }  

 这里首先判断次beandefinetion的override方法是否为空,如果是则使用JDK反射进行生成,否则使用CGLIB进行生成。(这里的判断依据我不太明了,希望大牛们指出..)

 

2.依赖注入

完成了bean对象的生成,接下来就应该是核心的依赖注入了

再次回到AbstractAutowireCapableBeanFactory的doCreateBean方法中,依赖注入发生在populateBean(beanName, mbd, instanceWrapper)方法中

 

Java代码  收藏代码
  1. protected void populateBean(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw) {  
  2.     PropertyValues pvs = mbd.getPropertyValues();  
  3.   
  4.     if (bw == null) {  
  5.         if (!pvs.isEmpty()) {  
  6.             throw new BeanCreationException(  
  7.                     mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");  
  8.         }  
  9.         else {  
  10.             // Skip property population phase for null instance.  
  11.             return;  
  12.         }  
  13.     }  
  14.   
  15.     // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the  
  16.     // state of the bean before properties are set. This can be used, for example,  
  17.     // to support styles of field injection.  
  18.     boolean continueWithPropertyPopulation = true;  
  19.   
  20.     if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {  
  21.         for (BeanPostProcessor bp : getBeanPostProcessors()) {  
  22.             if (bp instanceof InstantiationAwareBeanPostProcessor) {  
  23.                 InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
  24.                 if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {  
  25.                     continueWithPropertyPopulation = false;  
  26.                     break;  
  27.                 }  
  28.             }  
  29.         }  
  30.     }  
  31.   
  32.     if (!continueWithPropertyPopulation) {  
  33.         return;  
  34.     }  
  35.   
  36.     if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||  
  37.             mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  38.         MutablePropertyValues newPvs = new MutablePropertyValues(pvs);  
  39.   
  40.         // Add property values based on autowire by name if applicable.  
  41.         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {  
  42.             autowireByName(beanName, mbd, bw, newPvs);  
  43.         }  
  44.   
  45.         // Add property values based on autowire by type if applicable.  
  46.         if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {  
  47.             autowireByType(beanName, mbd, bw, newPvs);  
  48.         }  
  49.   
  50.         pvs = newPvs;  
  51.     }  
  52.   
  53.     boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();  
  54.     boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);  
  55.   
  56.     if (hasInstAwareBpps || needsDepCheck) {  
  57.         PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw);  
  58.         if (hasInstAwareBpps) {  
  59.             for (BeanPostProcessor bp : getBeanPostProcessors()) {  
  60.                 if (bp instanceof InstantiationAwareBeanPostProcessor) {  
  61.                     InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;  
  62.                     pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);  
  63.                     if (pvs == null) {  
  64.                         return;  
  65.                     }  
  66.                 }  
  67.             }  
  68.         }  
  69.         if (needsDepCheck) {  
  70.             checkDependencies(beanName, mbd, filteredPds, pvs);  
  71.         }  
  72.     }  
  73.   
  74.     applyPropertyValues(beanName, mbd, bw, pvs);  
  75. }  

 首先判断是否有BeanPostProcessors(hasInstantiationAwareBeanPostProcessors()) 如果有,则进行一些修改处理。然后判断是否有自动装配属性(mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
    mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE)

如果有则进行自动装配。最后应用依赖注入applyPropertyValues(beanName, mbd, bw, pvs);

 

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. }  

 

这里首先对所有的属性值进行一次深拷贝(deepCopy.add(pv)),将拷贝的值注入bean

最后进行依赖注入,在BeanWrapper中完成 bw.setPropertyValues(new MutablePropertyValues(deepCopy))

具体实现是在BeanWrapper中

 

Java代码  收藏代码
  1. @Override  
  2. public void setPropertyValue(PropertyValue pv) throws BeansException {  
  3.     PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;  
  4.     if (tokens == null) {  
  5.         String propertyName = pv.getName();  
  6.         BeanWrapperImpl nestedBw;  
  7.         try {  
  8.             nestedBw = getBeanWrapperForPropertyPath(propertyName);  
  9.         }  
  10.         catch (NotReadablePropertyException ex) {  
  11.             throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,  
  12.                     "Nested property in path '" + propertyName + "' does not exist", ex);  
  13.         }  
  14.         tokens = getPropertyNameTokens(getFinalPath(nestedBw, propertyName));  
  15.         if (nestedBw == this) {  
  16.             pv.getOriginalPropertyValue().resolvedTokens = tokens;  
  17.         }  
  18.         nestedBw.setPropertyValue(tokens, pv);  
  19.     }  
  20.     else {  
  21.         setPropertyValue(tokens, pv);  
  22.     }  
  23. }  

 这里面主要是生成一个PropertyTokenHolder对象  然后重载到setPropertyValue(tokens, pv)中

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

 在这个非常长的方法里面真正完成了依赖注入的实现,对property进行类型的判断 (propValue.getClass().isArray(),propValue instanceof List,propValue instanceof Map)然后根据类型分别进行注入处理。到此,依赖注入基本到底。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多