Ioc容器依赖注入-Spring 源码(2)

前端之家收集整理的这篇文章主要介绍了Ioc容器依赖注入-Spring 源码(2)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Ioc容器依赖注入-Spring 源码(2)

目录:

Ioc容器beanDefinition-Spring源码(1)

Ioc容器依赖注入-Spring 源码(2)

Ioc容器BeanPostProcessor-Spring 源码(3)

上篇中组装出了一个beanName:beanDefinition的ConcurrentHashMap,接下来就是把这些bean像织网一样联系起来。

从Abstractbeanfactory的getBean方法入手:

  @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name,null,false);
    }

    @Override
    public <T> T getBean(String name,Class<T> requiredType) throws BeansException {
        return doGetBean(name,requiredType,false);
    }

    @Override
    public Object getBean(String name,Object... args) throws BeansException {
        return doGetBean(name,args,false);
    }

    public <T> T getBean(String name,Class<T> requiredType,false);
    }

doGetBean方法

protected <T> T doGetBean(
      final String name,final Class<T> requiredType,final Object[] args,boolean typeCheckOnly)
      throws BeansException {
   //筛选出null,&符号的代表自身
   final String beanName = transformedBeanName(name);
   Object 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 + "'");
         }
      }
      //factorybean情况
      bean = getObjectForBeanInstance(sharedInstance,name,beanName,null);
   }

   else {
      // Fail if we're already creating this bean instance:
      // We're assumably within a circular reference.
      if (isPrototypeCurrentlyInCreation(beanName)) {
         throw new BeanCurrentlyInCreationException(beanName);
      }

      // Check if bean definition exists in this factory.
      beanfactory parentbeanfactory = getParentbeanfactory();
      if (parentbeanfactory != null && !containsBeanDefinition(beanName)) {
         // Not found -> check parent.
         String nameToLookup = originalBeanName(name);
         if (args != null) {
            // Delegation to parent with explicit args.
            return (T) parentbeanfactory.getBean(nameToLookup,args);
         }
         else {
            // No args -> delegate to standard getBean method.
            return parentbeanfactory.getBean(nameToLookup,requiredType);
         }
      }

      if (!typeCheckOnly) {
         markBeanAsCreated(beanName);
      }

      try {
         final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
         checkMergedBeanDefinition(mbd,args);

         // 获取这个bean依赖的对象,进入for循环迭代调用getBean方法,开始织网
         String[] dependsOn = mbd.getDependsOn();
         if (dependsOn != null) {
            for (String dependsOnBean : dependsOn) {
               if (isDependent(beanName,dependsOnBean)) {
                  throw new BeanCreationException(mbd.getResourceDescription(),"Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
               }
               registerDependentBean(dependsOnBean,beanName);
               // 迭代
               getBean(dependsOnBean);
            }
         }

         // 最终创建bean
         // 单例
         if (mbd.isSingleton()) {
            sharedInstance = getSingleton(beanName,new ObjectFactory<Object>() {
               @Override
               public Object getObject() throws BeansException {
                  try {
                     return createBean(beanName,mbd,args);
                  }
                  catch (BeansException ex) {
                     // Explicitly remove instance from singleton cache: It might have been put there
                     // eagerly by the creation process,to allow for circular reference resolution.
                     // Also remove any beans that received a temporary reference to the bean.
                     destroySingleton(beanName);
                     throw ex;
                  }
               }
            });
            bean = getObjectForBeanInstance(sharedInstance,mbd);
         }
        // 多例
         else if (mbd.isPrototype()) {
            // It's a prototype -> create a new instance.
            Object prototypeInstance = null;
            try {
               beforePrototypeCreation(beanName);
               prototypeInstance = createBean(beanName,args);
            }
            finally {
               afterPrototypeCreation(beanName);
            }
            bean = getObjectForBeanInstance(prototypeInstance,mbd);
         }
        // 自定义配置的scop
         else {
            String scopeName = mbd.getScope();
            final Scope scope = this.scopes.get(scopeName);
            if (scope == null) {
               throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
            }
            try {
               Object scopedInstance = scope.get(beanName,new ObjectFactory<Object>() {
                  @Override
                  public Object getObject() throws BeansException {
                     beforePrototypeCreation(beanName);
                     try {
                        return createBean(beanName,args);
                     }
                     finally {
                        afterPrototypeCreation(beanName);
                     }
                  }
               });
               bean = getObjectForBeanInstance(scopedInstance,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);
            }
         }
      }
      catch (BeansException ex) {
         cleanupAfterBeanCreationFailure(beanName);
         throw ex;
      }
   }

   // Check if required type matches the type of the actual bean instance.
   if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
      try {
         return getTypeConverter().convertIfNecessary(bean,requiredType);
      }
      catch (TypeMismatchException ex) {
         if (logger.isDebugEnabled()) {
            logger.debug("Failed to convert bean '" + name + "' to required type [" +
                  ClassUtils.getQualifiedName(requiredType) + "]",ex);
         }
         throw new BeanNotOfrequiredTypeException(name,bean.getClass());
      }
   }
   return (T) bean;
}

无论单例还是多例模式的scop都是调用AbstractAutowireCapablebeanfactory的createBean方法->doCreateBean方法来创建bean:

protected Object createBean(String beanName,RootBeanDefinition mbd,Object[] args) throws BeanCreationException {
   if (logger.isDebugEnabled()) {
      logger.debug("Creating instance of bean '" + beanName + "'");
   }
   RootBeanDefinition mbdToUse = mbd;

   // Make sure bean class is actually resolved at this point,and
   // clone the bean definition in case of a dynamically resolved Class
   // which cannot be stored in the shared merged bean definition.
   Class<?> resolvedClass = resolveBeanClass(mbd,beanName);
   if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
      mbdToUse = new RootBeanDefinition(mbd);
      mbdToUse.setBeanClass(resolvedClass);
   }

   // Prepare method overrides.
   try {
      mbdToUse.prepareMethodOverrides();
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),"Validation of method overrides Failed",ex);
   }

   try {
      // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
      Object bean = resolveBeforeInstantiation(beanName,mbdToUse);
      if (bean != null) {
         return bean;
      }
   }
   catch (Throwable ex) {
      throw new BeanCreationException(mbdToUse.getResourceDescription(),"BeanPostProcessor before instantiation of bean Failed",ex);
   }

   Object beanInstance = doCreateBean(beanName,mbdToUse,args);
   if (logger.isDebugEnabled()) {
      logger.debug("Finished creating instance of bean '" + beanName + "'");
   }
   return beanInstance;
}
protected Object doCreateBean(final String beanName,final RootBeanDefinition mbd,final Object[] args) {
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factorybeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName,args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd,beanType,beanName);
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like beanfactoryAware.
        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<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName,bean);
                }
            });
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName,instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName,exposedObject,mbd);
            }
        }
        catch (Throwable ex) {
            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
                throw (BeanCreationException) ex;
            }
            else {
                throw new BeanCreationException(mbd.getResourceDescription(),"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.");
                    }
                }
            }
        }

        // Register bean as disposable.
        try {
            registerDisposableBeanIfNecessary(beanName,bean,mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(),"Invalid destruction signature",ex);
        }

        return exposedObject;
    }

以上的单例部分交由DefaultSingletonBeanRegistry管理,采用Registry of Singleton 模式,我在单例的文章里也补充了

可以想象:网由点和线组成

1,createBeanInstance(beanName,args)生成包装了bean的对象,就是生成好点。

protected BeanWrapper createBeanInstance(String beanName,Object[] args) {
        // Make sure bean class is actually resolved at this point.
        Class<?> beanClass = resolveBeanClass(mbd,beanName);

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(),"Bean class isn't public,and non-public access not allowed: " + beanClass.getName());
        }
    // 工厂方法创建bean
        if (mbd.getFactoryMethodName() != null)  {
            return instantiateUsingFactoryMethod(beanName,args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            synchronized (mbd.constructorArgumentLock) {
                if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        if (resolved) {
            if (autowireNecessary) {
                return autowireConstructor(beanName,null);
            }
            else {
                return instantiateBean(beanName,mbd);
            }
        }

        // 使用构造函数创建bean
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass,beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName,ctors,args);
        }

        // 使用默认的构造函数创建bean
        return instantiateBean(beanName,mbd);
    }
    // 使用默认的构造函数创建bean
    protected BeanWrapper instantiateBean(final String beanName,final RootBeanDefinition mbd) {
        try {
            Object beanInstance;
            final beanfactory parent = this;
            if (System.getSecurityManager() != null) {
                beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                      //
                        return getInstantiationStrategy().instantiate(mbd,parent);
                    }
                },getAccessControlContext());
            }
            else {
                beanInstance = getInstantiationStrategy().instantiate(mbd,parent);
            }
            BeanWrapper bw = new BeanWrapperImpl(beanInstance);
            initBeanWrapper(bw);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(),"Instantiation of bean Failed",ex);
        }
    }

SimpleInstantiationStrategy的instantiate(RootBeanDefinition bd,String beanName,beanfactory owner)方法

public Object instantiate(RootBeanDefinition bd,beanfactory owner) {
   // 如果没有override method 就走构造函数 否则走CGLIB
   if (bd.getMethodOverrides().isEmpty()) {
      Constructor<?> constructorToUse;
      synchronized (bd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse == null) {
            final Class<?> clazz = bd.getBeanClass();
            if (clazz.isInterface()) {
               throw new BeanInstantiationException(clazz,"Specified class is an interface");
            }
            try {
               if (System.getSecurityManager() != null) {
                  constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                     @Override
                     public Constructor<?> run() throws Exception {
                        return clazz.getDeclaredConstructor((Class[]) null);
                     }
                  });
               }
               else {
                  constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
               }
               bd.resolvedConstructorOrFactoryMethod = constructorToUse;
            }
            catch (Exception ex) {
               throw new BeanInstantiationException(clazz,"No default constructor found",ex);
            }
         }
      }
      // BeanUtils 方法
      return BeanUtils.instantiateClass(constructorToUse);
   }
   else {
      // Must generate CGLIB subclass.
      return instantiateWithMethodInjection(bd,owner);
   }
}

以上已经把ioc容器管理的bean创建的过程都走完了,接下来就是把这些bean之间的关系建立起来,有了点,再做一下线,就可以变成网了。

2,populateBean(beanName,instanceWrapper);方法来做好线的事。

protected void populateBean(String beanName,BeanWrapper bw) {
    // 需要注入的值
        PropertyValues pvs = mbd.getPropertyValues();

        if (bw == null) {
            if (!pvs.isEmpty()) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(),"Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }

        // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
        // state of the bean before properties are set. This can be used,for example,// to support styles of field injection.
        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;
        }

        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

            // Add property values based on autowire by name if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName,bw,newPvs);
            }

            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName,newPvs);
            }

            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw,mbd.allowCaching);
            if (hasInstAwareBpps) {
                for (BeanPostProcessor bp : getBeanPostProcessors()) {
                    if (bp instanceof InstantiationAwareBeanPostProcessor) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs,filteredPds,bw.getWrappedInstance(),beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName,pvs);
            }
        }
    // 注入操作
        applyPropertyValues(beanName,pvs);
    }
    
    protected void applyPropertyValues(String beanName,BeanDefinition mbd,BeanWrapper bw,PropertyValues pvs) {
        if (pvs == null || pvs.isEmpty()) {
            return;
        }

        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;

        if (System.getSecurityManager() != null) {
            if (bw instanceof BeanWrapperImpl) {
                ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
            }
        }

        if (pvs instanceof MutablePropertyValues) {
            mpvs = (MutablePropertyValues) pvs;
            if (mpvs.isConverted()) {
                // Shortcut: use the pre-converted values as-is.
                try {
                    bw.setPropertyValues(mpvs);
                    return;
                }
                catch (BeansException ex) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(),"Error setting property values",ex);
                }
            }
            original = mpvs.getPropertyValueList();
        }
        else {
            original = Arrays.asList(pvs.getPropertyValues());
        }

        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
        //处理类
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this,converter);

        // Create a deep copy,resolving any references for values.
        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,converter);
                }
                // Possibly store converted value in merged bean definition,// in order to avoid re-conversion for every created bean instance.
                if (resolvedValue == originalValue) {
                    if (convertible) {
                        pv.setConvertedValue(convertedValue);
                    }
                    deepCopy.add(pv);
                }
                else if (convertible && originalValue instanceof TypedStringValue &&
                        !((TypedStringValue) originalValue).isDynamic() &&
                        !(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();
        }

        // Set our (possibly massaged) deep copy.
        try {
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(),ex);
        }
    }

什么类型都会调用到TypeConverterDelegate.convertIfNecessary来获得注入的bean

public <T> T convertIfNecessary(String propertyName,Object oldValue,Object newValue,Class<T> requiredType,TypeDescriptor typeDescriptor) throws IllegalArgumentException {

   // Custom editor for this type?
   PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType,propertyName);

   ConversionFailedException conversionAttemptEx = null;

   // No custom editor but custom ConversionService specified?
   ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
   if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {
      TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
      if (conversionService.canConvert(sourceTypeDesc,typeDescriptor)) {
         try {
            return (T) conversionService.convert(newValue,sourceTypeDesc,typeDescriptor);
         }
         catch (ConversionFailedException ex) {
            // fallback to default conversion logic below
            conversionAttemptEx = ex;
         }
      }
   }

   Object convertedValue = newValue;

   // Value not of required type?
   if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType,convertedValue))) {
      if (requiredType != null && Collection.class.isAssignableFrom(requiredType) && convertedValue instanceof String) {
         TypeDescriptor elementType = typeDescriptor.getElementTypeDescriptor();
         if (elementType != null && Enum.class.isAssignableFrom(elementType.getType())) {
            convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
         }
      }
      if (editor == null) {
         editor = findDefaultEditor(requiredType);
      }
      convertedValue = doConvertValue(oldValue,convertedValue,editor);
   }

   boolean standardConversion = false;

   if (requiredType != null) {
      // Try to apply some standard type conversion rules if appropriate.

      if (convertedValue != null) {
         if (Object.class == requiredType) {
            return (T) convertedValue;
         }
         else if (requiredType.isArray()) {
            // Array required -> apply appropriate conversion of elements.
            if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
               convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
            }
            return (T) convertToTypedArray(convertedValue,requiredType.getComponentType());
         }
         else if (convertedValue instanceof Collection) {
            // Convert elements to target type,if determined.
            convertedValue = convertToTypedCollection(
                  (Collection<?>) convertedValue,typeDescriptor);
            standardConversion = true;
         }
         else if (convertedValue instanceof Map) {
            // Convert keys and values to respective target type,if determined.
            convertedValue = convertToTypedMap(
                  (Map<?,?>) convertedValue,typeDescriptor);
            standardConversion = true;
         }
         if (convertedValue.getClass().isArray() && Array.getLength(convertedValue) == 1) {
            convertedValue = Array.get(convertedValue,0);
            standardConversion = true;
         }
         if (String.class == requiredType && ClassUtils.isPrimitiveOrWrapper(convertedValue.getClass())) {
            // We can stringify any primitive value...
            return (T) convertedValue.toString();
         }
         else if (convertedValue instanceof String && !requiredType.isInstance(convertedValue)) {
            if (conversionAttemptEx == null && !requiredType.isInterface() && !requiredType.isEnum()) {
               try {
                  Constructor<T> strCtor = requiredType.getConstructor(String.class);
                  return BeanUtils.instantiateClass(strCtor,convertedValue);
               }
               catch (NoSuchMethodException ex) {
                  // proceed with field lookup
                  if (logger.isTraceEnabled()) {
                     logger.trace("No String constructor found on type [" + requiredType.getName() + "]",ex);
                  }
               }
               catch (Exception ex) {
                  if (logger.isDebugEnabled()) {
                     logger.debug("Construction via String Failed for type [" + requiredType.getName() + "]",ex);
                  }
               }
            }
            String trimmedValue = ((String) convertedValue).trim();
            if (requiredType.isEnum() && "".equals(trimmedValue)) {
               // It's an empty enum identifier: reset the enum value to null.
               return null;
            }
            convertedValue = attemptToConvertStringToEnum(requiredType,trimmedValue,convertedValue);
            standardConversion = true;
         }
         else if (convertedValue instanceof Number && Number.class.isAssignableFrom(requiredType)) {
            convertedValue = NumberUtils.convertNumberToTargetClass(
                  (Number) convertedValue,(Class<Number>) requiredType);
            standardConversion = true;
         }
      }
      else {
         // convertedValue == null
         if (javaUtilOptionalEmpty != null && requiredType.equals(javaUtilOptionalEmpty.getClass())) {
            convertedValue = javaUtilOptionalEmpty;
         }
      }

      if (!ClassUtils.isAssignableValue(requiredType,convertedValue)) {
         if (conversionAttemptEx != null) {
            // Original exception from former ConversionService call above...
            throw conversionAttemptEx;
         }
         else if (conversionService != null) {
            // ConversionService not tried before,probably custom editor found
            // but editor couldn't produce the required type...
            TypeDescriptor sourceTypeDesc = TypeDescriptor.forObject(newValue);
            if (conversionService.canConvert(sourceTypeDesc,typeDescriptor)) {
               return (T) conversionService.convert(newValue,typeDescriptor);
            }
         }

         // Definitely doesn't match: throw IllegalArgumentException/IllegalStateException
         StringBuilder msg = new StringBuilder();
         msg.append("Cannot convert value of type [").append(ClassUtils.getDescriptiveType(newValue));
         msg.append("] to required type [").append(ClassUtils.getQualifiedName(requiredType)).append("]");
         if (propertyName != null) {
            msg.append(" for property '").append(propertyName).append("'");
         }
         if (editor != null) {
            msg.append(": PropertyEditor [").append(editor.getClass().getName()).append(
                  "] returned inappropriate value of type [").append(
                  ClassUtils.getDescriptiveType(convertedValue)).append("]");
            throw new IllegalArgumentException(msg.toString());
         }
         else {
            msg.append(": no matching editors or conversion strategy found");
            throw new IllegalStateException(msg.toString());
         }
      }
   }

   if (conversionAttemptEx != null) {
      if (editor == null && !standardConversion && requiredType != null && Object.class != requiredType) {
         throw conversionAttemptEx;
      }
      logger.debug("Original ConversionService attempt Failed - ignored since " +
            "PropertyEditor based conversion eventually succeeded",conversionAttemptEx);
   }

   return (T) convertedValue;
}

放入bean的操作是BeanWrapperImpl的基类上的setPropertyValue实现

protected void setPropertyValue(PropertyTokenHolder tokens,PropertyValue pv) throws BeansException {
        String propertyName = tokens.canonicalName;
        String actualName = tokens.actualName;

        if (tokens.keys != null) {
            // Apply indexes and map keys: fetch value for all keys but the last one.
            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,tokens.keys.length - 1);
            Object propValue;
            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);
            }
            // Set value for last key.
            String key = tokens.keys[tokens.keys.length - 1];
            if (propValue == null) {
                // null map value case
                if (isAutoGrowNestedPaths()) {
                    // TODO: cleanup,this is pretty hacky
                    int lastKeyIndex = tokens.canonicalName.lastIndexOf('[');
                    getterTokens.canonicalName = tokens.canonicalName.substring(0,lastKeyIndex);
                    propValue = setDefaultValue(getterTokens);
                }
                else {
                    throw new NullValueInNestedPathException(getRootClass(),"Cannot access indexed value in property referenced " +
                                    "in indexed property path '" + propertyName + "': returned null");
                }
            }
            if (propValue.getClass().isArray()) {
                PropertyHandler ph = getLocalPropertyHandler(actualName);
                Class<?> requiredType = propValue.getClass().getComponentType();
                int arrayIndex = Integer.parseInt(key);
                Object oldValue = null;
                try {
                    if (isExtractOldValueForEditor() && arrayIndex < Array.getLength(propValue)) {
                        oldValue = Array.get(propValue,arrayIndex);
                    }
                    Object convertedValue = convertIfNecessary(propertyName,oldValue,pv.getValue(),ph.nested(tokens.keys.length));
                    int length = Array.getLength(propValue);
                    if (arrayIndex >= length && arrayIndex < this.autoGrowCollectionLimit) {
                        Class<?> componentType = propValue.getClass().getComponentType();
                        Object newArray = Array.newInstance(componentType,arrayIndex + 1);
                        System.arraycopy(propValue,newArray,0,length);
                        setPropertyValue(actualName,newArray);
                        propValue = getPropertyValue(actualName);
                    }
                    Array.set(propValue,arrayIndex,convertedValue);
                }
                catch (IndexOutOfBoundsException ex) {
                    throw new InvalidPropertyException(getRootClass(),"Invalid array index in property path '" + propertyName + "'",ex);
                }
            }
            else if (propValue instanceof List) {
                PropertyHandler ph = getPropertyHandler(actualName);
                Class<?> requiredType = ph.getCollectionType(tokens.keys.length);
                List<Object> list = (List<Object>) propValue;
                int index = Integer.parseInt(key);
                Object oldValue = null;
                if (isExtractOldValueForEditor() && index < list.size()) {
                    oldValue = list.get(index);
                }
                Object convertedValue = convertIfNecessary(propertyName,ph.nested(tokens.keys.length));
                int size = list.size();
                if (index >= size && index < this.autoGrowCollectionLimit) {
                    for (int i = size; i < index; i++) {
                        try {
                            list.add(null);
                        }
                        catch (NullPointerException ex) {
                            throw new InvalidPropertyException(getRootClass(),"Cannot set element with index " + index + " in List of size " +
                                            size + ",accessed using property path '" + propertyName +
                                            "': List does not support filling up gaps with null elements");
                        }
                    }
                    list.add(convertedValue);
                }
                else {
                    try {
                        list.set(index,convertedValue);
                    }
                    catch (IndexOutOfBoundsException ex) {
                        throw new InvalidPropertyException(getRootClass(),"Invalid list index in property path '" + propertyName + "'",ex);
                    }
                }
            }
            else if (propValue instanceof Map) {
                PropertyHandler ph = getLocalPropertyHandler(actualName);
                Class<?> mapKeyType = ph.getMapKeyType(tokens.keys.length);
                Class<?> mapValueType = ph.getMapValueType(tokens.keys.length);
                Map<Object,Object> map = (Map<Object,Object>) propValue;
                // IMPORTANT: Do not pass full property name in here - property editors
                // must not kick in for map keys but rather only for map values.
                TypeDescriptor typeDescriptor = TypeDescriptor.valueOf(mapKeyType);
                Object convertedMapKey = convertIfNecessary(null,null,key,mapKeyType,typeDescriptor);
                Object oldValue = null;
                if (isExtractOldValueForEditor()) {
                    oldValue = map.get(convertedMapKey);
                }
                // Pass full property name and old value in here,since we want full
                // conversion ability for map values.
                Object convertedMapValue = convertIfNecessary(propertyName,mapValueType,ph.nested(tokens.keys.length));
                map.put(convertedMapKey,convertedMapValue);
            }
            else {
                throw new InvalidPropertyException(getRootClass(),"Property referenced in indexed property path '" + propertyName +
                                "' is neither an array nor a List nor a Map; returned value was [" + propValue + "]");
            }
        }

        else {
            PropertyHandler ph = getLocalPropertyHandler(actualName);
            if (ph == null || !ph.isWritable()) {
                if (pv.isOptional()) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Ignoring optional value for property '" + actualName +
                                "' - property not found on bean class [" + getRootClass().getName() + "]");
                    }
                    return;
                }
                else {
                    throw createNotWritablePropertyException(propertyName);
                }
            }
            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() && ph.isReadable()) {
                            try {
                                oldValue = ph.getValue();
                            }
                            catch (Exception ex) {
                                if (ex instanceof PrivilegedActionException) {
                                    ex = ((PrivilegedActionException) ex).getException();
                                }
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Could not read prevIoUs value of property '" +
                                            this.nestedPath + propertyName + "'",ex);
                                }
                            }
                        }
                        valueToApply = convertForProperty(
                                propertyName,originalValue,ph.toTypeDescriptor());
                    }
                    pv.getOriginalPropertyValue().conversionNecessary = (valueToApply != originalValue);
                }
                ph.setValue(object,valueToApply);
            }
            catch (TypeMismatchException ex) {
                throw ex;
            }
            catch (InvocationTargetException ex) {
                PropertyChangeEvent propertyChangeEvent =
                        new PropertyChangeEvent(this.rootObject,pv.getValue());
                if (ex.getTargetException() instanceof ClassCastException) {
                    throw new TypeMismatchException(propertyChangeEvent,ph.getPropertyType(),ex.getTargetException());
                }
                else {
                    Throwable cause = ex.getTargetException();
                    if (cause instanceof UndeclaredThrowableException) {
                        // May happen e.g. with Groovy-generated methods
                        cause = cause.getCause();
                    }
                    throw new MethodInvocationException(propertyChangeEvent,cause);
                }
            }
            catch (Exception ex) {
                PropertyChangeEvent pce =
                        new PropertyChangeEvent(this.rootObject,pv.getValue());
                throw new MethodInvocationException(pce,ex);
            }
        }
    }
    // 使用反射机制,执行注入set方法注入bean
    public void setValue(final Object object,Object valueToApply) throws Exception {
            final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
                    ((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
                    this.pd.getWriteMethod());
            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()) && !writeMethod.isAccessible()) {
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged(new PrivilegedAction<Object>() {
                        @Override
                        public Object run() {
                            writeMethod.setAccessible(true);
                            return null;
                        }
                    });
                }
                else {
                    writeMethod.setAccessible(true);
                }
            }
            final Object value = valueToApply;
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                            writeMethod.invoke(object,value);
                            return null;
                        }
                    },acc);
                }
                catch (PrivilegedActionException ex) {
                    throw ex.getException();
                }
            }
            else {
                writeMethod.invoke(getWrappedInstance(),value);
            }
        }

----------------------

永远爱汀汀

猜你在找的设计模式相关文章