码迷,mamicode.com
首页 > 编程语言 > 详细

Spring IoC 属性赋值阶段

时间:2020-07-04 13:53:35      阅读:77      评论:0      收藏:0      [点我收藏+]

标签:currently   ict   manage   resource   并且   except   return   converter   sar   

前言

本系列全部基于 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 {
    // 这里一般就是set方法
    final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor)this.pd).getWriteMethodForActualAccess() : this.pd.getWriteMethod());
    // 利用反射调用set方法给属性赋值
    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 IoC 属性赋值阶段

标签:currently   ict   manage   resource   并且   except   return   converter   sar   

原文地址:https://www.cnblogs.com/leisurexi/p/13234465.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!