spring源码解析 — 注入属性

前面的文件已经解析了Spring构造bean(未注入属性)的过程,现在继续解析spring注入属性的过程。

在解析spring读取xml配置文章说过,spring会将xml属性配置信息转化为spring内部的表示类,并结合属性name,type等元数据构造PropertyValue,存放在BeanDefinition#propertyValues。

而在解析spring构造bean的文章中说过,spring注入属性的方法在

AbstractAutowireCapableBeanFactory#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
        PropertyValues pvs = mbd.getPropertyValues();

        ...
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {    // #1
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {    // #2
                        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) {    // #3
                autowireByName(beanName, mbd, bw, newPvs);
            }

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

            pvs = newPvs;
        }

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

        if (hasInstAwareBpps || needsDepCheck) {    // #5
            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);    // #6
    }

}

#1 查找spring上下文是否存在InstantiationAwareBeanPostProcessor。

InstantiationAwareBeanPostProcessor也是spring提供的扩展接口,它继承自BeanPostProcessor,并添加了postProcessBeforeInstantiation,postProcessAfterInstantiation,postProcessPropertyValues这三个方法。

#2 存在InstantiationAwareBeanPostProcessor,调用postProcessAfterInstantiation方法

#3 处理通过name自动装配

#4 处理通过type自动装配

#5 调用InstantiationAwareBeanPostProcessor#postProcessPropertyValues扩展方法,很重要,这里完成@Value,@Autowired注解的解析,后面有对应文章解析

#6 解析BeanDefinition#propertyValues中的属性

AbstractAutowireCapableBeanFactory#autowireByName

protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        if (containsBean(propertyName)) {
            Object bean = getBean(propertyName);    // #1
            pvs.add(propertyName, bean);    // #2
            registerDependentBean(propertyName, beanName);    // #3
            if (logger.isDebugEnabled()) {
                logger.debug("Added autowiring by name from bean name '" + beanName +
                        "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            ...
        }
    }
}

#1 通过name获取bean

#2 添加到BeanDefinition#propertyValues,交给下面流程处理

#3 声明bean之间的依赖,bean销毁时要判断bean的依赖

autowireByType 这里就不复述了。

AbstractAutowireCapableBeanFactory#applyPropertyValues

protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        ...

        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);    // #1
            }
            else {
                String propertyName = pv.getName();
                Object originalValue = pv.getValue();
                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);    // #2
                Object convertedValue = resolvedValue;
                boolean convertible = bw.isWritableProperty(propertyName) &&
                        !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
                if (convertible) {
                    convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);    // #3
                }
                // 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);    // #4
                    }
                    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;    // #5
                    deepCopy.add(new PropertyValue(pv, convertedValue));
                }
            }
        }
        if (mpvs != null && !resolveNecessary) {
            mpvs.setConverted();
        }

        // Set our (possibly massaged) deep copy.
        try {
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));    // #6
        }
        catch (BeansException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Error setting property values", ex);
        }
    }

#1 属性已处理,直接复用

#2 解析bean引用(如RuntimeBeanReference,RuntimeBeanNameReference),获取引用的bean,对于集合属性,如ManagedArray,ManagedList,如果集合中的元素是bean引用,也会被解析

TypedStringValue则会提取value的值。

#3 根据目标属性进行转换

xml配置都是string,如果属性的类型是long,date,这里进行转换

#4 缓存结果,避免每次构建bean时都重复操作

#5 无法缓存,只能复制结果用于后面流程

#6 赋值给bean

转化

下面看看转化过程

AbstractAutowireCapableBeanFactory#convertForProperty

private Object convertForProperty(Object value, String propertyName, BeanWrapper bw, TypeConverter converter) {
        if (converter instanceof BeanWrapperImpl) {            
            return ((BeanWrapperImpl) converter).convertForProperty(value, propertyName);    // #1
        }
        else {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
            return converter.convertIfNecessary(value, pd.getPropertyType(), methodParam);    // #2
        }
    }

#1 默认的转化方式

#2 使用自定义转化方式

看看默认的转化方式,BeanWrapperImpl#convertForProperty -> TypeConverterDelegate#convertIfNecessary

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

        PropertyEditor editor = this.propertyEditorRegistry.findCustomEditor(requiredType, propertyName);

        ConversionFailedException conversionAttemptEx = null;

        ConversionService conversionService = this.propertyEditorRegistry.getConversionService();
        if (editor == null && conversionService != null && newValue != null && typeDescriptor != null) {    // #1
            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;

        if (editor != null || (requiredType != null && !ClassUtils.isAssignableValue(requiredType, convertedValue))) {    // #2
            if (typeDescriptor != null && requiredType != null && Collection.class.isAssignableFrom(requiredType) &&
                    convertedValue instanceof String) {
                TypeDescriptor elementTypeDesc = typeDescriptor.getElementTypeDescriptor();
                if (elementTypeDesc != null) {
                    Class<?> elementType = elementTypeDesc.getType();
                    if (Class.class == elementType || Enum.class.isAssignableFrom(elementType)) {
                        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()) {    // #3
                    if (convertedValue instanceof String && Enum.class.isAssignableFrom(requiredType.getComponentType())) {
                        convertedValue = StringUtils.commaDelimitedListToStringArray((String) convertedValue);
                    }
                    return (T) convertToTypedArray(convertedValue, propertyName, requiredType.getComponentType());
                }
                ...
            }
            else {
                // convertedValue == null
                if (javaUtilOptionalEmpty != null && requiredType == javaUtilOptionalEmpty.getClass()) {
                    convertedValue = javaUtilOptionalEmpty;    // #4
                }
            }

            if (!ClassUtils.isAssignableValue(requiredType, convertedValue)) {
                ... // #5
            }
        }

        

        return (T) convertedValue;
    }

#1 PropertyEditor为空,使用ConversionService

#2 PropertyEditor不为空,使用PropertyEditor

#3 处理数组,集合等类型的属性,这里会遍历集合元素,递归调用convertIfNecessary转化,再收集处理结果。

#4 对转化结果是空值的情况进行处理

#5 异常情况,会重复调用一遍conversionService

PropertyEditor,ConversionService都可以自定义属性的转化操作。

赋值

AbstractAutowireCapableBeanFactory#applyPropertyValues方法 #6 步骤负责赋值给bean的属性。

这里调用AbstractNestablePropertyAccessor#setPropertyValues -> AbstractNestablePropertyAccessor#setPropertyValue

public void setPropertyValue(PropertyValue pv) throws BeansException {
        PropertyTokenHolder tokens = (PropertyTokenHolder) pv.resolvedTokens;
        if (tokens == null) {
            String propertyName = pv.getName();
            AbstractNestablePropertyAccessor nestedPa;
            try {
                nestedPa = getPropertyAccessorForPropertyPath(propertyName);    // #1
            }
            catch (NotReadablePropertyException ex) {
                throw new NotWritablePropertyException(getRootClass(), this.nestedPath + propertyName,
                        "Nested property in path '" + propertyName + "' does not exist", ex);
            }
            tokens = getPropertyNameTokens(getFinalPath(nestedPa, propertyName));
            if (nestedPa == this) {
                pv.getOriginalPropertyValue().resolvedTokens = tokens;
            }
            nestedPa.setPropertyValue(tokens, pv);    // #2
        }
        else {
            setPropertyValue(tokens, pv);
        }
    }

#1 根据propertyName获取不同的属性访问器(set方法引用)

getPropertyAccessorForPropertyPath返回的是BeanWrapperImpl,他继承了AbstractNestablePropertyAccessor。

这里支持嵌套属性,如Blog中存在author属性,而Author存在name属性,对Blog的bean可配置author.name,这里返回的是blog的author属性对应的BeanWrapperImpl。

#2

AbstractNestablePropertyAccessor#setPropertyValue -> AbstractNestablePropertyAccessor#processLocalProperty -> PropertyHandler#setValue -> BeanWrapperImpl#setValue

可以看到直接调用set方法了。

如果您觉得本文不错,欢迎关注我的微信公众号,您的关注是我坚持的动力!

spring源码解析 -- 注入属性

原文 

https://segmentfault.com/a/1190000022529007

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » spring源码解析 — 注入属性

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址