• 欢迎访问 winrains 的个人网站!
  • 本网站主要从互联网整理和收集了与Java、网络安全、Linux等技术相关的文章,供学习和研究使用。如有侵权,请留言告知,谢谢!

Spring IoC源码分析之Bean的加载(7):属性填充

Spring winrains 来源:大王叫下 11个月前 (10-15) 35次浏览

在上篇文章中,我们详细分析了doCreateBean()中的4步:单例模式的循环依赖处理,本文接着分析doCreateBean()的第5步“属性填充”,也就是populateBean()方法。

首先回顾下CreateBean的主流程:

  1. 如果是单例模式,从factoryBeanInstanceCache 缓存中获取BeanWrapper 实例对象并删除缓存
  2. 调用 createBeanInstance() 实例化 bean
  3. 后置处理
  4. 单例模式的循环依赖处理
  5. 属性填充
  6. 初始化 bean 实例对象
  7. 依赖检查
  8. 注册bean的销毁方法

本章我们主要分析第5步:
在Spring中属性注入有三种方式:

  • xml配置
  • 注解方式
  • 手动get\set方法

xml方式如<beans>节点中的default-autowire属性
注解方式如:@Value()、@Resource、@Autowire、@Qualifier
本文我们主要分析 注解方式 的属性注入

一、populateBean(beanName, mbd, instanceWrapper)

  //AbstractAutowireCapableBeanFactory.java
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 {
            // 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.
    /*
     * 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会。
     * 关于这段后置引用,官方的解释是:让用户可以自定义属性注入。比如用户实现一
     * 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过
     * postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。当然,如果无
     * 特殊需求,直接使用配置中的信息注入即可。另外,Spring 并不建议大家直接实现
     * InstantiationAwareBeanPostProcessor 接口,如果想实现这种类型的后置处理器,更建议
     * 通过继承 InstantiationAwareBeanPostProcessorAdapter 抽象类实现自定义后置处理器。
     */
    boolean continueWithPropertyPopulation = true;
    // bean 不是"合成"的,即未由应用程序本身定义 && 持有 InstantiationAwareBeanPostProcessor
<1> if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        // 遍历所有的 BeanPostProcessors
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 返回值为是否继续填充 bean
                // postProcessAfterInstantiation:如果应该在 bean上面设置属性则返回 true,否则返回 false
                // 一般情况下,应该是返回true 。
                // 返回 false 的话,将会阻止在此 Bean 实例上调用任何后续的 InstantiationAwareBeanPostProcessor 实例。
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    // 如果后置处理器发出停止填充命令,则终止后续操作
    if (!continueWithPropertyPopulation) {
        return;
    }
    //获取Bean的属性值
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
    //处理依赖注入
    //xml方式    即xml中<beans>节点中的default-autowire属性
<2> if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        // 将 PropertyValues 封装成 MutablePropertyValues 对象
        // MutablePropertyValues 允许对属性进行简单的操作,并提供构造函数以支持Map的深度复制和构造。
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        //根据Bean名称进行autowiring自动装配处理
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        //根据Bean类型进行autowiring自动装配处理
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }
    // 是否已经注册了 InstantiationAwareBeanPostProcessors
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    //是否需要依赖检查(xml)
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
        //属性注入(注解方式)
    //已经注册IABP && 需要依赖检查
<3> if (hasInstAwareBpps || needsDepCheck) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    // 具体处理属性注入(注解方式)!!! 如@Value()、@Resource、@Autowire
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        //依赖检查 (xml)
<4>     if (needsDepCheck) {
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
<5> if (pvs != null) {
        //对属性进行注入 (xml)
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

主要分为以下几个步骤:

  • 判断是否有自定义属性注入
  • 属性注入(xml方式)
  • 属性注入(注解方式)
  • 依赖检查(xml方式)
  • 注入属性(xml方式)

1.1、判断是否有自定义属性注入

在上述代码<1>处:

/*
 * 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会。
 * 关于这段后置引用,官方的解释是:让用户可以自定义属性注入。比如用户实现一
 * 个 InstantiationAwareBeanPostProcessor 类型的后置处理器,并通过
 * postProcessAfterInstantiation 方法向 bean 的成员变量注入自定义的信息。当然,如果无
 * 特殊需求,直接使用配置中的信息注入即可。另外,Spring 并不建议大家直接实现
 * InstantiationAwareBeanPostProcessor 接口,如果想实现这种类型的后置处理器,更建议
 * 通过继承 InstantiationAwareBeanPostProcessorAdapter 抽象类实现自定义后置处理器。
 */
 boolean continueWithPropertyPopulation = true;
    // bean 不是"合成"的,即未由应用程序本身定义 && 持有 InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    // 遍历所有的 BeanPostProcessors
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 返回值为是否继续填充 bean
            // postProcessAfterInstantiation:如果应该在 bean上面设置属性则返回 true,否则返回 false
            // 一般情况下,应该是返回true 。
            // 返回 false 的话,将会阻止在此 Bean 实例上调用任何后续的 InstantiationAwareBeanPostProcessor 实例。
            if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                continueWithPropertyPopulation = false;
                break;
            }
        }
    }
}
// 如果后置处理器发出停止填充命令,则终止后续操作
if (!continueWithPropertyPopulation) {
    return;
}

这部分逻辑注释上已经写的很清楚了。

1.2、属性注入(xml方式)

//xml方式    即xml中<beans>节点中的default-autowire属性
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
    // 将 PropertyValues 封装成 MutablePropertyValues 对象
    // MutablePropertyValues 允许对属性进行简单的操作,并提供构造函数以支持Map的深度复制和构造。
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    // Add property values based on autowire by name if applicable.
    //根据Bean名称进行autowiring自动装配处理
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }
    // Add property values based on autowire by type if applicable.
    //根据Bean类型进行autowiring自动装配处理
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
    }
    pvs = newPvs;
}

这部分代码主要是来处理XML方式的属性注入,例如xml中<beans>节点中的default-autowire属性,因为本次Spring系列主要是分析注解方式的,这里就不详细分析了。感性趣的朋友可以自己趣了解下~

1.2、属性注入(注解方式)

PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
    if (hasInstAwareBpps) {
    for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof InstantiationAwareBeanPostProcessor) {
            InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
            // 处理依赖注入(注解方式) 如@Value()、@Resource、@Autowire
            pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
            if (pvs == null) {
                return;
            }
        }
    }
}

这段代码就是我们要分析的核心。
首先是判断是否已经注册了InstantiationAwareBeanPostProcessor(实例化Bean的后置处理器),如果注册了,就遍历所有的后置处理器。 我们先来了解下InstantiationAwareBeanPostProcessor的类图结构:

InstantiationAwareBeanPostProcessor是一个关于对象实例化前后以及实例化后设置propertyValues的回调处理器。 它有三个方法:

//这个方法用来在对象实例化前直接返回一个对象(如代理对象)来代替通过内置的实例化流程创建对象;
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}
//在对象实例化完毕执行populateBean之前 如果返回false则spring不再对对应的bean实例进行自动依赖注入。
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    return true;
}
 //这里是在spring处理完默认的成员属性,应用到指定的bean之前进行回调,可以用来检查和修改属性,最终返回的PropertyValues会应用到bean中
    //@Autowired、@Resource、@Value等就是根据这个方法来实现最终注入依赖的属性的。
@Nullable
default PropertyValues postProcessPropertyValues(
        PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    return pvs;
}

我们主要看第三个方法postProcessPropertyValues(),这个方法就是通过注解进行属性注入的具体实现。
该方法主要有3个实现,分别对应了不同的注解。

  • AutowiredAnnotationBeanPostProcessor
    可以处理@Autowire、@Value
  • CommonAnnotationBeanPostProcessor
    可以处理@Resource
  • RequiredAnnotationBeanPostProcessor
    可以处理@Required

1.2.1、AutowiredAnnotationBeanPostProcessor

是Spring容器专门处理配置了自动依赖注入装配相关注解(@Autowire、@Value以及其他JSR-330注解)的Bean后置处理器。详细说明见Spring注解@Autowired源码分析

1.2.2、CommonAnnotationBeanPostProcessor

CommonAnnotationBeanPostProcessor是Spring中用于处理JavaEE5中常用注解(主要是EJB相关的注解)和Java6中关于JAX-WS相关的注解,可以处理@PostConstruct、@PreDestroy等Bean生命周期相关事件的注解,该后置处理最核心的是处理@Resource注解,同时还可以处理JAX-WS相关的注解。详细说明见Spring注解@Resource源码分析

总结

到这里就已经完成了注解方式所有属性的注入了。

作者:大王叫下

来源:https://juejin.im/post/5d7ef148f265da03c428c09e


版权声明:文末如注明作者和来源,则表示本文系转载,版权为原作者所有 | 本文如有侵权,请及时联系,承诺在收到消息后第一时间删除 | 如转载本文,请注明原文链接。
喜欢 (1)