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


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

    目录:

    Ioc容器beanDefinition-Spring 源码(1)

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

    Ioc容器BeanPostProcessor-Spring 源码(3)

    事件机制-Spring 源码(4)

    AOP执行增强-Spring 源码系列(5)

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

    从AbstractBeanFactory的getBean方法入手:

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

    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, beanName, args);
    
             // 获取这个bean依赖的对象,进入for循环迭代调用getBean方法,开始织网
             String[] dependsOn = mbd.getDependsOn();
             if (dependsOn != null) {
                for (String dependsOnBean : dependsOn) {
                   if (isDependent(beanName, dependsOnBean)) {
                      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                            "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, name, beanName, mbd);
             }
            // 多例
             else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                   beforePrototypeCreation(beanName);
                   prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                   afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, 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, mbd, args);
                         }
                         finally {
                            afterPrototypeCreation(beanName);
                         }
                      }
                   });
                   bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                   throw new BeanCreationException(beanName,
                         "Scope '" + scopeName + "' is not active for the current thread; consider " +
                         "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                         ex);
                }
             }
          }
          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, requiredType, 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(),
                beanName, "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(), beanName,
                "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, mbd, 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, mbd, bean);
                    }
                });
            }
    
            // Initialize the bean instance.
            Object exposedObject = bean;
            try {
                populateBean(beanName, mbd, 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(), beanName, "Initialization of bean failed", ex);
                }
            }
    
            if (earlySingletonExposure) {
                Object earlySingletonReference = getSingleton(beanName, false);
                if (earlySingletonReference != null) {
                    if (exposedObject == bean) {
                        exposedObject = earlySingletonReference;
                    }
                    else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                        String[] dependentBeans = getDependentBeans(beanName);
                        Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                        for (String dependentBean : dependentBeans) {
                            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                                actualDependentBeans.add(dependentBean);
                            }
                        }
                        if (!actualDependentBeans.isEmpty()) {
                            throw new BeanCurrentlyInCreationException(beanName,
                                    "Bean with name '" + beanName + "' has been injected into other beans [" +
                                    StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                                    "] in its raw version as part of a circular reference, but has eventually been " +
                                    "wrapped. This means that said other beans do not use the final version of the " +
                                    "bean. This is often the result of over-eager type matching - consider using " +
                                    "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                        }
                    }
                }
            }
    
            // Register bean as disposable.
            try {
                registerDisposableBeanIfNecessary(beanName, bean, mbd);
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
            }
    
            return exposedObject;
        }

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

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

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

    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, 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(), beanName,
                        "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
            }
        // 工厂方法创建bean
            if (mbd.getFactoryMethodName() != null)  {
                return instantiateUsingFactoryMethod(beanName, mbd, 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, mbd, null, 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, mbd, 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, beanName, parent);
                        }
                    }, getAccessControlContext());
                }
                else {
                    beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
                }
                BeanWrapper bw = new BeanWrapperImpl(beanInstance);
                initBeanWrapper(bw);
                return bw;
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
            }
        }

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

    public Object instantiate(RootBeanDefinition bd, String beanName, 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, beanName, owner);
       }
    }

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

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

    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        // 需要注入的值
            PropertyValues pvs = mbd.getPropertyValues();
    
            if (bw == null) {
                if (!pvs.isEmpty()) {
                    throw new BeanCreationException(
                            mbd.getResourceDescription(), beanName, "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, mbd, bw, newPvs);
                }
    
                // Add property values based on autowire by type if applicable.
                if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                    autowireByType(beanName, mbd, bw, newPvs);
                }
    
                pvs = newPvs;
            }
    
            boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
            boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
    
            if (hasInstAwareBpps || needsDepCheck) {
                PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, 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, mbd, filteredPds, pvs);
                }
            }
        // 注入操作
            applyPropertyValues(beanName, mbd, bw, 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(), beanName, "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, beanName, mbd, 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, bw, 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(), beanName, "Error setting property values", 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, requiredType, 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, propertyName, requiredType.getComponentType());
             }
             else if (convertedValue instanceof Collection) {
                // Convert elements to target type, if determined.
                convertedValue = convertToTypedCollection(
                      (Collection<?>) convertedValue, propertyName, requiredType, typeDescriptor);
                standardConversion = true;
             }
             else if (convertedValue instanceof Map) {
                // Convert keys and values to respective target type, if determined.
                convertedValue = convertToTypedMap(
                      (Map<?, ?>) convertedValue, propertyName, requiredType, 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, sourceTypeDesc, 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, 0, 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(), this.nestedPath + propertyName,
                                "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(),
                                requiredType, 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, 0, newArray, 0, length);
                            setPropertyValue(actualName, newArray);
                            propValue = getPropertyValue(actualName);
                        }
                        Array.set(propValue, arrayIndex, convertedValue);
                    }
                    catch (IndexOutOfBoundsException ex) {
                        throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
                                "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, oldValue, pv.getValue(),
                            requiredType, 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(), this.nestedPath + propertyName,
                                        "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(), this.nestedPath + propertyName,
                                    "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, oldValue, pv.getValue(),
                            mapValueType, ph.nested(tokens.keys.length));
                    map.put(convertedMapKey, convertedMapValue);
                }
                else {
                    throw new InvalidPropertyException(getRootClass(), this.nestedPath + propertyName,
                            "Property referenced in indexed property path '" + propertyName +
                                    "' is neither an array nor a List nor a Map; returned value was [" + 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, oldValue, 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, this.nestedPath + propertyName, oldValue, 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, this.nestedPath + propertyName, oldValue, 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);
                }
            }

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

    永远爱汀汀

  • 相关阅读:
    SQL Server 的事务和锁 图解
    pxc 集群
    Supported_Hardware#4G_LTE_cards_and_modems
    手机性能天梯图
    无线上网卡制式
    python源码学习
    SQLSERVER里面RR隔离级别没有GAP锁
    JAVA EE 博客实例
    REDIS 配制
    SQL SERVER 函数与SQL语法
  • 原文地址:https://www.cnblogs.com/killbug/p/6349109.html
Copyright © 2020-2023  润新知