zoukankan      html  css  js  c++  java
  • Spring IoC 属性赋值阶段

    前言

    本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本。因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析。

    本篇文章主要介绍 Spring IoC 容器中 bean 的属性赋值阶段。

    正文

    我们在Spring IoC bean 的创建一文中分析创建 bean 实例的主要流程,此时创建出来的 bean 还是个属性未赋值的实例,在创建完之后会进入 populateBean() 方法,即进入属性赋值阶段。我们简单回顾一下,上次分析过的 doCreateBean() 方法:

    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
    
        // 实例化 bean
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            // 如果bean的作用域是singleton,则需要移除未完成的FactoryBean实例的缓存
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            // 通过构造函数反射创建bean的实例,但是属性并未赋值,见下文详解
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        // 获取bean的实例
        final Object bean = instanceWrapper.getWrappedInstance(); 
        // 获取bean的类型
        Class<?> beanType = instanceWrapper.getWrappedClass(); 
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }
    
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    // BeanDefinition 合并后的回调,见下文详解
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } 
                // 省略异常处理...
                mbd.postProcessed = true;
            }
        }
    
        // bean的作用域是单例 && 允许循环引用 && 当前bean正在创建中
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
        // 如果允许bean提前曝光
        if (earlySingletonExposure) {
            // 将beanName和ObjectFactory形成的key-value对放入singletonFactories缓存中
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
    
        Object exposedObject = bean;
        try {
            // 给 bean 的属性赋值
            populateBean(beanName, mbd, instanceWrapper);
            // 初始化 bean
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        } 
        // 省略部分代码
    }
    

    属性赋值

    AbstractAutowireCapableBeanFactory#populateBean

    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            } else {
                return;
            }
        }
      
        // 给InstantiationAwareBeanPostProcessors最后一次机会在属性设置前来改变bean
        // 例如:可以用来支持属性注入的类型
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    // 这里会调用bean实例化后的生命周期回调,返回false会跳过下面的属性赋值阶段
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        return;
                    }
                }
            }
        }
        // 获取PropertyValues
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
        // 获取依赖注入类型
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
      	// 如果依赖注入类型是 byName 或者 byType
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
          	// 赋值pvs到可修改的MutablePropertyValues
            MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // 根据名称自动注入,见下文详解
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }
            // 根据类型自动注入,见下文详解
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }
    
        // 是否有注册InstantiationAwareBeanPostProcessors的实现类
        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    
        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            // 遍历并找到InstantiationAwareBeanPostProcessor的实现类,调用处理属性值的后置处理方法
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
                        pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        // 如果属性值的后置处理方法返回null,直接返回,不会进行底下的属性值应用阶段
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    
        if (pvs != null) {
            // 属性填充,见下文详解
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }
    

    上面方法首先会调用 bean 的实例化后生命周期回调方法,如果返回 false 会跳过下面的属性赋值阶段。关于 InstantiationAwareBeanPostProcessors 接口在Spring IoC bean 的创建一文中介绍过,这里不再赘述。接着判断是否是按 名称 或者 类型 自动注入属性并填入 newPvs 中,接着调用 bean 属性填充前的生命周期回调。属性填充前生命周期回调方法有两个 postProcessProperties()postProcessPropertyValues(),第一个是 Spring 5.1 新加的,后面的是老的,已经被标记为过时;首先会调用 postProcessProperties() 如果返回空调用 postProcessPropertyValues(),否则直接使用返回的 PropertyValuespostProcessPropertyValues() 如果返回空会直接跳过属性填充阶段,不为空直接使用返回的 PropertyValues

    按照名称依赖注入

    AbstractAutowireCapableBeanFactory#autowireByName

    protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
        // 寻找bw中需要依赖注入的属性名称
        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        // 遍历需要注入的bean
        for (String propertyName : propertyNames) {
            if (containsBean(propertyName)) {
                // 调用getBean()方法获取bean
                Object bean = getBean(propertyName);
                // 将需要注入bean的实例加入到pvs
                pvs.add(propertyName, bean);
                // 注册依赖关系
                registerDependentBean(propertyName, beanName);
            }
        }
    }
    

    上面的方法很简单,就是寻找 bean 的非简单类型并且不存在于 mbd.getPropertyValues() 中的属性,然后遍历调用 getBean() 方法去获取实例,完成注入。

    非简单类型就是指除去8个原始类型、String类型、Number类型、Date类型、URL类型、URI类型的其它类型。

    registerDependentBean() 方法在Spring IoC bean 的加载一文中有分析过,这里不再赘述。

    按照类型依赖注入

    AbstractAutowireCapableBeanFactory#autowireByType

    protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
    
        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
    
        Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
        // 获取bean中非简单属性
        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for (String propertyName : propertyNames) {
            try {
                PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
                // 根据类型注入永远不要注入Object类型,你细细地品一下
                if (Object.class != pd.getPropertyType()) {
                    // 获取属性的可写方法,一般是set方法
                    MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                    boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
                    DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                    // 依赖解决,最后返回符合条件需要注入的bean实例
                    Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                    if (autowiredArgument != null) {
                        // 需要注入的bean实例不为空,加入到pvc
                        pvs.add(propertyName, autowiredArgument);
                    }
                    for (String autowiredBeanName : autowiredBeanNames) {
                        // 注册依赖关系
                        registerDependentBean(autowiredBeanName, beanName);
                    }
                    autowiredBeanNames.clear();
                }
            } catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
            }
        }
    }
    

    上面方法中的 resolveDependency() 方法在Spring IoC bean 的创建一文中介绍过,这里不再赘述。

    属性赋值

    AbstractAutowireCapableBeanFactory#applyPropertyValues

    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        // 属性为空,直接返回
        if (pvs.isEmpty()) {
            return;
        }
    
        if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
            ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
        }
    
        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;
    
        if (pvs instanceof MutablePropertyValues) {
            mpvs = (MutablePropertyValues) pvs;
            // 快捷方式,如果属性已经转换过,直接填充进BeanWrapper
            if (mpvs.isConverted()) {
                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);
    
        // 创建深拷贝,解决引用的问题
        List<PropertyValue> deepCopy = new ArrayList<>(original.size());
        boolean resolveNecessary = false;
        // 遍历属性,将属性转换为对应的类型
        for (PropertyValue pv : original) {
            // 如果pv类型转换过,直接添加进deepCopy
            if (pv.isConverted()) {
                deepCopy.add(pv);
            } else {
                // 进行转换
                // 拿到pv原始属性名和属性值
                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);
                }
                // 进行类型转换
                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);
                }
                // 在合并的BeanDefinition中存储转换后的值,以避免为每个创建的bean实例重新转换
                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();
        }
    
        try {
            // 填充bean属性值
            bw.setPropertyValues(new MutablePropertyValues(deepCopy));
        } catch (BeansException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Error setting property values", ex);
        }
    }
    

    上面代码中的 bw.setPropertyValues() 方法最终会调用 BeanWrapperImpl#setVlaue() 方法,如下:

    public void setValue(final @Nullable Object value) throws Exception {
        // 这里一般就是setter方法
        final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
    ((GenericTypeAwarePropertyDescriptor)this.pd).getWriteMethodForActualAccess() : this.pd.getWriteMethod());
        // 利用反射调用setter方法给属性赋值
        ReflectionUtils.makeAccessible(writeMethod);
        writeMethod.invoke(getWrappedInstance(), value);
    
    }
    

    下图是我 debug 时的截图,可以看到基本上就是在调用属性的 setter 方法:

    注意:没有 setter 方法时会抛出异常。

    总结

    本篇文章主要分析了 Spring IoC 的属性赋值阶段的流程,Spring 在此阶段也提供了2个扩展点;分别是 bean 的实例化后和属性赋值前,即 InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation() 方法和 postProcessProperties() 方法。需要注意的是在 XML 中配置的 autowire 属性,不管是 byName 还是 byType 都需要 setter 方法,但是我们平时在使用 @Autowire 注解时并不需要 settter 方法,原因会在分析 @Autowire 注解时讲述。

    最后,我模仿 Spring 写了一个精简版,代码会持续更新。地址:https://github.com/leisurexi/tiny-spring

  • 相关阅读:
    Uva 11991 Easy Prblem from Rujia Liu ?
    BANK && IT
    随机数发生器(对拍)-----对比测试
    HDU 1695(GCD)
    欧拉定理与费马定理,离散对数定理
    POJ 2352 (stars)
    线段树
    codeforces 51C(Three Base Stations)
    codeforces 165B(Burning Midnight Oil)
    POJ 2785(4 Values whose Sum is 0)
  • 原文地址:https://www.cnblogs.com/leisurexi/p/13234465.html
Copyright © 2011-2022 走看看