SpringIOC之Bean属性填充的逻辑

总体流程总结:

当我们显示或者隐式地调用AbstractBeanFactory 的 getBean(...) 方法时,会触发 Bean 的加载。
对于不同作用域的 Bean,底层都会调用 AbstractAutowireCapableBeanFactory 的 createBean(...)方法进行创建。
创建 Bean 的过程中,获取到的一个实例对象后,需要获取相关属性值,然后注入到 Bean 中,其中获取属性值有三种模式:
AUTOWIRE_NO,默认,不获取相关属性值
AUTOWIRE_BY_NAME,通过名称获取没有定义属性值的"对象"的属性值,通过 getBean(String beanName) 查找
AUTOWIRE_BY_TYPE,通过类型获取没有定义属性值的"对象"的属性值,依赖注入的方式
默认情况下,获取到已定义的属性值后不会通过上面的方式去找属性值,在后续有一个属性值的后置处理,
会调用所有的 InstantiationAwareBeanPostProcessor 处理器的 postProcessProperties 方法进行处理,例如 Spring 内部有两个 InstantiationAwareBeanPostProcessor 处理器:
AutowiredAnnotationBeanPostProcessor,解析 @Autowired 和 @Value 注解标注的属性,获取对应属性值
CommonAnnotationBeanPostProcessor,会解析 @Resource 注解标注的属性,获取对应的属性值
在获取到所有的属性值后然后通过反射机制设置到 Bean 中

    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();
                if (originalValue == AutowiredPropertyMarker.INSTANCE) {
                    Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
                    if (writeMethod == null) {
                        throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
                    }
                    originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
                }
                // <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) 方法

  1. 没有转换过,则获取所有的属性值集合,放入 original 集合中

  1. 定义一个 deepCopy 集合,保存转换后的属性值

  1. 遍历所有的属性值,进行转换(如果有必要)

  1. 已经转换过,则直接添加到 deepCopy

  1. 否则,开始进行转换

  1. 表达式的处理(如果有必要的话),例如你在 XML 配置的属性值为 ${systenm.user},则会解析出对应的值

  1. 使用类型转换器转换属性值(如果有必要的话)

  1. 设置转换后的值,避免上面的各种判断

  1. 添加到 deepCopy

  1. 如果属性值不为空,且不需要每次都处理,则设置为已转换

  1. 将属性值设置到当前 Bean 中(反射机制),依赖注入的最终实现

调用 BeanWrapperImpl#setPropertyValues(PropertyValues) 方法


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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder_Boy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值