跳至主要內容

12.Bean 的属性填充阶段

Java突击队大约 19 分钟

12.Bean 的属性填充阶段

该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址open in new window 进行阅读

Spring 版本:5.1.14.RELEASE

开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》open in new window这一篇文章

该系列其他文章请查看:《死磕 Spring 之 IoC 篇 - 文章导读》open in new window

Bean 的属性填充阶段

当我们显示或者隐式地调用AbstractBeanFactorygetBean(...) 方法时,会触发 Bean 的加载,在《开启 Bean 的加载》open in new window文章中分析了整个加载过程。

对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactorycreateBean(...)方法进行创建,在《Bean 的创建过程》open in new window文章中分析了整个创建过程。创建 Bean 的过程中,在获取到的一个实例对象后,里面的相关属性也许是空的,那么接下来要做的就是将需要填充的属性进行依赖注入,然后再进行后续的初始化工作。整个的属性填充过程非常复杂,因为配置的属性值可能是一个表达式,需要解析,类型也可能不对,需要进行类型转换,还可能是一个对象,需要找到对应的 Bean 然后注入(依赖注入),存在有各种处理,本文将会分析创建 Bean 过程中的属性填充阶段。

回顾

先来回顾一下创建 Bean 过程中属性填充阶段对应的代码:

// AbstractAutowireCapableBeanFactory#doCreateBean(...) 方法
// Initialize the bean instance.
// 开始初始化 bean
Object exposedObject = bean;
try {
    // `<4>` 对 bean 进行属性填充,注入对应的属性值
    populateBean(beanName, mbd, instanceWrapper);
    // `<5>` 初始化这个 exposedObject,调用其初始化方法
    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);
    }
}

在创建好实例对象后,这个对象的属性还没有赋值,所以将这个实例对象的相关属性进行赋值,也就是上面的第 <4>

开启 Bean 的属性填充

populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) 方法,属性填充,如下:

// AbstractAutowireCapableBeanFactory.java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // <1> 如果实例对象为空,则进行下面的判断
    if (bw == null) {
        // <1.1> 这个 Bean 有属性,则抛出异常
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        // `<1.2>` 否则,不用属性填充,直接 return
        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.
    // <2> 实例化阶段的后置处理,如果满足这两个条件
    if (!mbd.isSynthetic() // RootBeanDefinition 不是用户定义的(由 Spring 解析出来的)
            && hasInstantiationAwareBeanPostProcessors()) { // 是否有 InstantiationAwareBeanPostProcessor 处理器
        // <2.1> 遍历所有的 BeanPostProcessor
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            // 如果为 InstantiationAwareBeanPostProcessor 类型
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // <2.2> 对实例化对象进行后置处理
                // 注意如果返回 false,直接 return,不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return;
                }
            }
        }
    }

    // `<3>` 获取 pvs,承载当前对象的属性值
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // `<4>` 获取这个 Bean 的注入模式,默认为 **AUTOWIRE_NO**,例如可以通过 @Bean 注解的 autowire 属性配置注入模式
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    // <4.1> 如果注入模式为 **AUTOWIRE_BY_NAME** 或者 **AUTOWIRE_BY_TYPE**,则通过下面的方式获取属性值
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        // `<4.2>` 将 pvs 封装成 MutablePropertyValues 对象 newPvs(允许对属性进行相关操作)
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        // `<4.3>` **AUTOWIRE_BY_NAME** 模式,通过名称获取相关属性值,保存在 newPvs 中
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        // `<4.4>` **AUTOWIRE_BY_TYPE** 模式,通过类型获取相关属性值,保存在 newPvs 中
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        // `<4.5>` 将 newPvs 复制给 pvs
        pvs = newPvs;
    }

    // 是否有 InstantiationAwareBeanPostProcessor 处理器
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    // 是否需要进行依赖检查,默认为 true
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    // `<5>` 通过 InstantiationAwareBeanPostProcessor 处理器(如果有)对 pvs 进行处理
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }

        // <5.1> 遍历所有的 BeanPostProcessor
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            // 如果为 InstantiationAwareBeanPostProcessor 类型
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                /**
                 * Spring 内部的 InstantiationAwareBeanPostProcessor 处理器:
                 * {@link AutowiredAnnotationBeanPostProcessor#postProcessProperties} 会解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值;
                 * {@link org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties} 会解析 @Resource 注解标注的属性,获取对应的属性值
                 */
                // `<5.2>` 调用处理器的 postProcessProperties(...) 方法,对 pvs 进行后置处理
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                // <5.3> 如果上一步的处理结果为空,可能是新版本导致的(Spring 5.1 之前没有上面这个方法),则需要兼容老版本
                if (pvsToUse == null) {
                    // `<5.3.1>` 找到这个 Bean 的所有 java.beans.PropertyDescriptor 属性描述器(包含这个属性的所有信息)
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    // `<5.3.2>` 调用处理器的 postProcessPropertyValues(...) 方法,对 pvs 进行后置处理
                    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    // `<5.3.3>` 如果处理后的 PropertyValues 对象为空,直接 return,则不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充
                    if (pvsToUse == null) {
                        return;
                    }
                }
                // `<5.4>` 将处理后的 pvsToUse 复制给 pvs
                pvs = pvsToUse;
            }
        }
    }
    // <6> 依赖检查
    if (needsDepCheck) {
        // `<6.1>` 找到这个 Bean 的所有 java.beans.PropertyDescriptor 属性描述器(包含这个属性的所有信息)
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        // <6.2> 依赖检查,如果没有找到对应的属性值,则根据检查策略进行抛出异常(默认不会)
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    // `<7>` 如果 pvs 不为空,则将里面的属性值设置到当前 Bean 对应的属性中(依赖注入)
    // 前面找到的属性值并没有设置到 Bean 中,且属性值可能是一个表达式,类型也可能也不对,需要先进行处理和类型转换,然后再设置到该实例对象中
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

过程大致如下:

1、 如果实例对象为null,则进行下面的判断;

1、 这个Bean有属性,则抛出异常;
2、 否则,不用属性填充,直接return
2、 实例化阶段的后置处理,如果满足这两个条件:RootBeanDefinition不是用户定义的(由Spring解析出来的)、是否有InstantiationAwareBeanPostProcessor处理器;

1、 遍历所有的BeanPostProcessor;
2、 如果为InstantiationAwareBeanPostProcessor类型,则对实例化对象进行后置处理;

注意,如果返回 false,直接 `return`,不会调用后面的 InstantiationAwareBeanPostProcessor 处理器,也不会进行接下来的属性填充

3、 获取pvs,承载当前对象的属性值;
4、 获取这个Bean的注入模式,默认为AUTOWIRE_NO,例如可以通过@Bean注解的autowire属性配置注入模式;

1、 如果注入模式为AUTOWIRE_BY_NAME或者AUTOWIRE_BY_TYPE,则通过下面的方式获取属性值;
2、pvs封装成MutablePropertyValues对象newPvs(允许对属性进行相关操作);
3、 AUTOWIRE_BY_NAME模式,通过名称获取相关属性值,保存在newPvs中,调用autowireByName(...)方法;
4、 AUTOWIRE_BY_TYPE模式,通过类型获取相关属性值,保存在newPvs中,调用autowireByType(...)方法;
5、newPvs复制给pvs
5、 通过InstantiationAwareBeanPostProcessor处理器(如果有)对pvs进行处理;

1、 遍历所有的BeanPostProcessor;
2、 如果为InstantiationAwareBeanPostProcessor类型,则调用其postProcessProperties(...)方法,对pvs进行后置处理;
3、 如果上一步的处理结果为空,可能是新版本导致的(Spring5.1之前没有上面这个方法),则需要兼容老版本

1.  尝试找到这个 Bean 的所有 `java.beans.PropertyDescriptor` 属性描述器(包含这个属性的所有信息)
2.  调用处理器的 `postProcessPropertyValues(...)` 方法,对 `pvs` 进行后置处理
3.  如果处理后的 PropertyValues 对象为空,直接 `return`,则不会调用后面的处理器,也不会进行接下来的属性填充

4、 将处理后的pvsToUse复制给pvs
6、 依赖检查;

1、 找到这个Bean的所有java.beans.PropertyDescriptor属性描述器(包含这个属性的所有信息);
2、 进行依赖检查,如果没有找到对应的属性值,则根据检查策略进行抛出异常(默认不会);
7、 如果pvs不为空,则将里面的属性值设置到当前Bean对应的属性中(依赖注入),调用applyPropertyValues(...)方法;

前面找到的属性值并没有设置到 Bean 中,且属性值可能是一个表达式,类型也可能也不对,需要先进行处理和类型转换,然后再设置到该实例对象中


整个的属性填充过程非常的复杂,接下来进行概括:

  • 允许你对实例化对象进行后置处理,处理结果为 false 表示不需要进行接下来的属性填充过程
  • 根据注入模式,找到没有配置属性值的对象属性,然后找到对应的 Bean,默认注入模式为不注入
  • 允许你对属性值进行后置处理,例如 @Autowired、@Value 等注解标注的属性会通过这里找到对应的属性值(或对象)
  • 上述过程仅找到了属性值,还没设置到当前实例对象中,所以最后一步才是真正的属性填充

上面有两种注入模式:AUTOWIRE_BY_NAMEAUTOWIRE_BY_TYPE,默认为 AUTOWIRE_NO,接下来先来看看这两种注入模式的实现

通过名称获取属性值

autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) 方法,通过名称获取相关属性值,如下:

// AbstractAutowireCapableBeanFactory.java
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    // <1> 获取当前 Bean 中不满意的非简单类型的属性名称,也就是没有定义属性值的"对象"属性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    // <2> 遍历这些对象属性的名称
    for (String propertyName : propertyNames) {
        // <3> 如果当前容器存在对应的 Bean(通过名称判断)
        if (containsBean(propertyName)) {
            // `<3.1>` 根据属性名称获取对应的 bean 对象(依赖查找)
            Object bean = getBean(propertyName);
            // `<3.2>` 将 bean 添加至 pvs
            pvs.add(propertyName, bean);
            // <3.3> 将两个 Bean 之间的依赖关系保存起来
            registerDependentBean(propertyName, beanName);
            if (logger.isTraceEnabled()) {
                logger.trace("Added autowiring by name from bean name '" + beanName +
                        "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        } else {
            if (logger.isTraceEnabled()) {
                logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                        "' by name: no matching bean found");
            }
        }
    }
}

过程并不复杂,大致如下:

1、 获取当前Bean中不满意的非简单类型的属性名称,也就是没有定义属性值的**"对象"**属性,如下:;

// AbstractAutowireCapableBeanFactory.java
protected String[] unsatisfiedNonSimpleProperties(AbstractBeanDefinition mbd, BeanWrapper bw) {
    Set<String> result = new TreeSet<>();
    // 获取已设置的属性值
    PropertyValues pvs = mbd.getPropertyValues();
    // 找到这个 Bean 的所有 PropertyDescriptor 属性描述器(包含这个属性的所有信息)
    PropertyDescriptor[] pds = bw.getPropertyDescriptors();
    // 遍历所有属性
    for (PropertyDescriptor pd : pds) {
        if (pd.getWriteMethod() != null // 有可写方法
                && !isExcludedFromDependencyCheck(pd) // 不忽略
                && !pvs.contains(pd.getName()) // 没有对应的属性值
                && !BeanUtils.isSimpleProperty(pd.getPropertyType())) // 不是简单类型(例如一个实体类)
        {
            result.add(pd.getName());
        }
    }
    // 返回这些不满意的非简单类型的属性
    return StringUtils.toStringArray(result);
}

2、 遍历这些对象属性的名称;
3、 如果当前容器存在对应的Bean(通过名称判断);

1、 根据属性名称获取对应的bean对象(依赖查找);
2、bean添加至pvs
3、 将两个Bean之间的依赖关系保存起来;

直接根据**"对象"**名称通过 getBean(String beanName) 获取到对应的对象(依赖查找

通过类型获取属性值

autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) 方法,通过类型获取相关属性值,如下:

// AbstractAutowireCapableBeanFactory.java
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    // <1> 获取 TypeConverter 类型转换器,用于取代默认的 PropertyEditor 类型转换器
    // 例如 Spring 3.0 之后的 ConversionService
    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
    // <2> 获取当前 Bean 中不满意的非简单类型的属性名称,也就是没有定义属性值的"对象"属性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    // <3> 遍历这些对象属性的名称
    for (String propertyName : propertyNames) {
        try {
            // `<3>` 获取这个属性的 java.beans.PropertyDescriptor 属性描述器(包含这个属性的所有信息)
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // <4> 如果不是 Object 类型(对 Object 类类型的 Bean 进行自动装配毫无意义),则尝试找到对应的对象
            if (Object.class != pd.getPropertyType()) {
                // <5> 找到这个属性的写方法
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                // 是否可以提前初始化
                boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                // <6> 创建对应的依赖注入描述对象
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                // <7> 依赖注入,找到该属性对应的对象
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                // `<8>` 如果找到属性对象,则将该其添加至 pvs
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                // <9> 将注入的属性对象和当前 Bean 之前的关系保存起来
                // 因为该属性可能是一个集合,找到了多个对象,所以这里是一个数组
                for (String autowiredBeanName : autowiredBeanNames) {
                    // 将 autowiredBeanName 与 beanName 的依赖关系保存
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isTraceEnabled()) {
                        logger.trace("Autowiring by type from bean name '" + beanName + "' via property '" +
                                propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                // 清空 autowiredBeanName 数组
                autowiredBeanNames.clear();
            }
        } catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}

过程大致如下:

1、 获取TypeConverter类型转换器,用于取代默认的PropertyEditor类型转换器;
2、 获取当前Bean中不满意的非简单类型的属性名称,也就是没有定义属性值的**"对象"属性,和通过名称注入的过程一样;
3、 遍历这些
"对象"**属性的名称,获取这个属性的java.beans.PropertyDescriptor属性描述器(包含这个属性的所有信息);
4、 如果不是Object类型(对Object类类型的Bean进行自动装配毫无意义),则尝试找到对应的对象;
5、 找到这个属性的写方法;
6、 创建对应的DependencyDescriptor依赖注入描述对象,默认required为false,表示找不到也没关系;
7、 依赖注入,找到该属性对应的对象,调用resolveDependency(...)方法;
8、 如果找到属性对象,则将该其添加至pvs
9、 将注入的属性对象和当前Bean之前的关系保存起来;

根据**"对象"名称通过 resolveDependency(...) 获取到对应的对象,该方法就是依赖注入**的底层实现,整个过程也非常复杂,所以将这部分内容放在下一篇《@Autowired 等注解的实现原理》open in new window文章中

属性值的后置处理

调用 InstantiationAwareBeanPostProcessor#postProcessProperties 方法,对前面属性值进行处理

在前面的AUTOWIRE_BY_NAMEAUTOWIRE_BY_TYPE两种注入模式中,找到的都是普通对象的属性值,例如 @Autowired、@Value 和 @Resource 注解并没有被解析,且默认的注入模式还是AUTOWIRE_NO,那这些注解是如何被解析的呢?Spring 内部有下面两个 InstantiationAwareBeanPostProcessor 处理器:

  • AutowiredAnnotationBeanPostProcessor,解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值
  • CommonAnnotationBeanPostProcessor,会解析 @Resource 注解标注的属性,获取对应的属性值

这里先提一下,具体的实现过程在下一篇《@Autowired 等注解的实现原理》open in new window文章中进行分析

属性填充

applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) 方法,属性填充

如果获取到的 pvs 属性值对象不为空,则将里面的属性值设置到当前 Bean 对应的属性中(依赖注入),我们知道前面找到的属性值并没有设置到 Bean 中,且属性值可能是一个表达式,类型也可能也不对,需要先进行处理和类型转换,然后再设置到该实例对象中,方法如下:

// AbstractAutowireCapableBeanFactory.java
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    // `<1>` 没有相关属性值,则直接 return 返回
    if (pvs.isEmpty()) {
        return;
    }
    if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
        ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    }

    // ------------------------开始属性值的转换与填充------------------------

    MutablePropertyValues mpvs = null;
    // 定义一个 original 集合,承载属性值(未进行转换)
    List<PropertyValue> original;

    // `<2>` 如果 pvs 是 MutablePropertyValues 类型,则可能已经处理过了
    if (pvs instanceof MutablePropertyValues) {
        mpvs = (MutablePropertyValues) pvs;
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                // <2.1> 属性值已经转换了,则将这些属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现!!!
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        // <2.2> 没有转换过,则获取所有的属性值集合
        original = mpvs.getPropertyValueList();
    }
    else {
        // <2.2> 获取所有的属性值集合
        original = Arrays.asList(pvs.getPropertyValues());
    }

    // 获取 TypeConverter 类型转换器,用于取代默认的 PropertyEditor 类型转换器
    // 例如 Spring 3.0 之后的 ConversionService
    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.
    // `<3>` 定义一个 deepCopy 集合,保存转换后的属性值
    List<PropertyValue> deepCopy = new ArrayList<>(original.size());
    boolean resolveNecessary = false;
    // <4> 遍历所有的属性值,进行转换(如果有必要)
    for (PropertyValue pv : original) {
        // `<4.1>` 已经转换过,则直接添加到 deepCopy 中
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        // <4.2> 否则,开始进行转换
        else {
            String propertyName = pv.getName();
            // 转换之前的属性值
            Object originalValue = pv.getValue();
            // `<4.2.1>` 表达式的处理(如果有必要的话),例如你在 XML 配置的属性值为 ${systenm.user},则会解析出对应的值
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            // 转换之后的属性值
            Object convertedValue = resolvedValue;
            // 该属性是否可以转换
            boolean convertible = bw.isWritableProperty(propertyName) && // 属性可写
                    !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName); // 不包含 . 和 [
            if (convertible) {
                // <4.2.2> 使用类型转换器转换属性值(如果有必要的话)
                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) {
                    // <4.2.3> 设置转换后的值,避免上面的各种判断
                    pv.setConvertedValue(convertedValue);
                }
                // `<4.2.4>` 添加到 deepCopy 中
                deepCopy.add(pv);
            }
            // 属否则属性值进行了转换
            else if (convertible // 可转换的
                    && originalValue instanceof TypedStringValue // 属性原始值是字符串类型
                    && !((TypedStringValue) originalValue).isDynamic() // 属性的原始类型值不是动态生成的字符串
                    && !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) // 属性的原始值不是集合或者数组类型
            {
                // <4.2.3> 设置转换后的值,避免上面的各种判断
                pv.setConvertedValue(convertedValue);
                // `<4.2.4>` 添加到 deepCopy 中
                deepCopy.add(pv);
            }
            // 否则
            else {
                // 这个属性每次都要处理,不能缓存
                resolveNecessary = true;
                // `<4.2.4>` 添加到 deepCopy 中
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }
    // <5> 如果属性值不为空,且不需要每次都处理,则设置为已转换
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    // Set our (possibly massaged) deep copy.
    try {
        // <6> 将属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现!!!
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

过程大致如下:

1、 没有相关属性值,则直接return返回;


开始属性值的转换与填充,先定义一个 original 集合,承载属性值(未进行转换)

1、 如果pvs是MutablePropertyValues类型,则可能已经处理过了,否则,获取所有的属性值集合,放入original集合中;

1、 属性值已经转换了,则将这些属性值设置到当前Bean中(反射机制),依赖注入的最终实现!!!;

    调用 BeanWrapperImpl#setPropertyValues(PropertyValues) 方法

2、 没有转换过,则获取所有的属性值集合,放入original集合中;
2、 定义一个deepCopy集合,保存转换后的属性值;
3、 遍历所有的属性值,进行转换(如果有必要);

1、 已经转换过,则直接添加到deepCopy中;
2、 否则,开始进行转换;

1.  表达式的处理(如果有必要的话),例如你在 XML 配置的属性值为 `${systenm.user}`,则会解析出对应的值
2.  使用类型转换器转换属性值(如果有必要的话)
3.  设置转换后的值,避免上面的各种判断
4.  添加到 `deepCopy` 中

4、 如果属性值不为空,且不需要每次都处理,则设置为已转换;
5、 将属性值设置到当前Bean中(反射机制),依赖注入的最终实现!!!;

调用 BeanWrapperImpl#setPropertyValues(PropertyValues) 方法

整个属性注入过程非常复杂,上面仅列出了关键步骤,可以看到最终会调用 BeanWrapperImpl#setPropertyValues(PropertyValues) 方法将属性值设置到 Bean 中

在Bean 的实例化阶段获取到的就是一个 BeanWrapperImpl 对象,所以这里调用的就是当前 Bean 的 setPropertyValues(PropertyValues) 方法,该方法的底层借助于 Java Beans 的 java.beans.PropertyDescriptor 属性描述器,获取到对应的写方法,然后通过反射机制设置当前 Bean 的属性值

总结

当我们显示或者隐式地调用AbstractBeanFactorygetBean(...) 方法时,会触发 Bean 的加载,在《开启 Bean 的加载》open in new window文章中分析了整个加载过程。

对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactorycreateBean(...)方法进行创建,在《Bean 的创建过程》open in new window文章中分析了整个创建过程。创建 Bean 的过程中,在获取到的一个实例对象后,需要获取相关属性值,然后注入到 Bean 中,其中获取属性值有三种模式:

  • AUTOWIRE_NO,默认,不获取相关属性值
  • AUTOWIRE_BY_NAME,通过名称获取没有定义属性值的**"对象"**的属性值,通过 getBean(String beanName) 查找
  • AUTOWIRE_BY_TYPE,通过类型获取没有定义属性值的**"对象"**的属性值,依赖注入的方式

默认情况下,获取到已定义的属性值后不会通过上面的方式去找属性值,在后续有一个属性值的后置处理,会调用所有的 InstantiationAwareBeanPostProcessor 处理器的 postProcessProperties 方法进行处理,例如 Spring 内部有两个 InstantiationAwareBeanPostProcessor 处理器:

  • AutowiredAnnotationBeanPostProcessor,解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值
  • CommonAnnotationBeanPostProcessor,会解析 @Resource 注解标注的属性,获取对应的属性值

在获取到所有的属性值后然后通过反射机制设置到 Bean 中

关于@Autowired、@Value 和 @Resource 注解的实现原理将在下一篇《@Autowired 等注解的实现原理》open in new window文章中进行分析

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址:open in new window