栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

深入理解Spring BeanPostProcessor & InstantiationAwareBeanPostProcessor

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

深入理解Spring BeanPostProcessor & InstantiationAwareBeanPostProcessor

在深入学习Spring Bean生命周期一节中,我们学习了Bean后置处理器BeanPostProcessor,用于在Bean初始化前后插入我们自己的逻辑(Bean增强,Bean代理等)。但是你知道BeanPostProcessor的子类InstantiationAwareBeanPostProcessor吗?他用于Bean实例化前后处理。

本节记录两者的区别以及简单原理分析。

1. 两者比较

Initialization为初始化的意思,Instantiation为实例化的意思。在Spring Bean生命周期中,实例化指的是创建Bean的过程,初始化指的是Bean创建后,对其属性进行赋值(populate bean)、后置处理等操作的过程,所以Instantiation执行时机先于Initialization。

1.1 类关系

先来看看BeanPostProcessor的类结构:

public interface BeanPostProcessor {
    // bean 初始化之前执行
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    // bean 初始化之后执行
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

InstantiationAwareBeanPostProcessor为BeanPostProcessor的子类,新增了三个额外的方法:

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        return null;
    }

    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        return null;
    }

    
    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
        return pvs;
    }
}
1.2 方法解析
  1. BeanPostProcessor
    • postProcessBeforeInitialization(Object bean, String beanName):bean:Bean实例;beanName:Bean名称。方法将在Bean实例的afterPropertiesSet方法或者自定义的init方法被调用前调用,此时Bean属性已经被赋值。方法返回原始Bean实例或者包装后的Bean实例,如果返回null,则后续的后置处理方法不再被调用。
    • postProcessAfterInitialization(Object bean, String beanName):bean:Bean实例;beanName:Bean名称。方法将在Bean实例的afterPropertiesSet方法或者自定义的init方法被调用后调用,此时Bean属性已经被赋值。方法返回原始Bean实例或者包装后的Bean实例,如果返回null,则后续的后置处理方法不再被调用。
  2. InstantiationAwareBeanPostProcessor
    • postProcessBeforeInstantiation(Class beanClass, String beanName):beanClass:待实例化的Bean类型;beanName:待实例化的Bean名称。方法作用为:在Bean实例化前调用该方法,返回值可以为代理后的Bean,以此代替Bean默认的实例化过程。返回值不为null时,后续只会调用BeanPostProcessor的 postProcessAfterInitialization方法,而不会调用别的后续后置处理方法(如postProcessAfterInitialization、postProcessBeforeInstantiation等方法);返回值也可以为null,这时候Bean将按默认方式初始化。
    • postProcessAfterInstantiation(Object bean, String beanName):bean:实例化后的Bean,此时属性还没有被赋值;beanName:Bean名称。方法作用为:当Bean通过构造器或者工厂方法被实例化后,当属性还未被赋值前,该方法会被调用,一般用于自定义属性赋值。方法返回值为布尔类型,返回true时,表示Bean属性需要被赋值;返回false表示跳过Bean属性赋值,并且InstantiationAwareBeanPostProcessor的postProcessProperties方法不会被调用。
1.3 执行时机对比

为了验证实例化和初始化的先后顺序,我们直接新建一个SpringBoot项目测试即可(我这里还使用之前的老项目):

Spring入口类名称为SpringDemoApplication。新建MyBeanPostProcessor实现BeanPostProcessor接口:

public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if ("springDemoApplication".equals(beanName)) {
            System.out.println("post processor before " + beanName + " initialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if ("springDemoApplication".equals(beanName)) {
            System.out.println("post processor after " + beanName + " initialization");
        }
        return bean;
    }

}

因为对所有的Bean生效,所以为了方便观察输出,这里仅当Bean名称为springDemoApplication时才打印输出。

注册进容器中:

@Bean
public MyBeanPostProcessor myBeanPostProcessor () {
    return new MyBeanPostProcessor();
}

接着新建MyBeanInstantiationPostProcessor实现InstantiationAwareBeanPostProcessor接口:

public class MyBeanInstantiationPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        if ("springDemoApplication".equals(beanName)) {
            System.out.println("post process before " + beanName + " instantiation");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if ("springDemoApplication".equals(beanName)) {
            System.out.println("post process after " + beanName + " instantiation");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if ("springDemoApplication".equals(beanName)) {
            System.out.println("post process " + beanName + " properties");
        }
        return pvs;
    }
}

记得配置到webconfig里面。

@Bean
public MyBeanInstantiationPostProcessor myBeanInstantiationPostProcessor() {
    return new MyBeanInstantiationPostProcessor();
}

启动程序,输出如下所示:

如果将MyBeanInstantiationPostProcessor的postProcessAfterInstantiation方法返回值改为false,程序输出如下:

2. 原理解析

postProcessAfterInitialization和InstantiationAwareBeanPostProcessor的方法都和Bean生命周期有关,要分析它们的实现原理自然要从Bean的创建过程入手。Bean创建的入口为AbstractAutowireCapableBeanFactory的createBean方法,查看其源码:

resolveBeforeInstantiation方法给Bean后置处理器一个返回目标Bean实例代理的机会,所以我们先重点关注下这个方法的源码。

该方法先于下面的doCreateBean方法,也就是说里面的操作逻辑实在Bean实例化之前完成的。

resolveBeforeInstantiation方法源码如下所示:

相关注释直接标记在代码中,方便查看。

@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    //beforeInstantiationResolved默认属性值为false,表示Bean实例化前置操作未执行
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        //判断是否有InstantiationAwareBeanPostProcessors处理器
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Class targetType = this.determineTargetType(beanName, mbd);
            //有的话执行PostProcessorsBeforeInstantiation方法
            if (targetType != null) {
                bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                //如果上述方法返回值不为null,则说明Bean已经在该方法中实例化了(代理,增加),那么直接执行BeanPostProcessor的PostProcessorsAfterInitialization方法
                if (bean != null) {
                    bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        //如果Bean不为null,则将beforeInstantiationResolved属性值设置true
        mbd.beforeInstantiationResolved = bean != null;
    }

    return bean;
}

上面方法返回的bean如果为空的话,AbstractAutowireCapableBeanFactory的createBean方法将继续往下执行doCreateBean方法:

查看doCreateBean方法源码:

这个时候我们会发现这里源码很多,我们先不看其他部分(Bean生命周期其他部分),重点关注populateBean和initializeBean方法。查看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 {
        if (!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
            Iterator var4 = this.getBeanPostProcessors().iterator();

            while(var4.hasNext()) {
                BeanPostProcessor bp = (BeanPostProcessor)var4.next();
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        //这个地方需要注意,当返回值为false的时候,直接返回,后续赋值操作不执行了
                        return;
                    }
                }
            }
        }

        // begin 这一块为属性赋值,aotowired,通过类型或者名称注入
        PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        if (resolvedAutowireMode == 1 || resolvedAutowireMode == 2) {
            MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
            if (resolvedAutowireMode == 1) {
                this.autowireByName(beanName, mbd, bw, newPvs);
            }

            if (resolvedAutowireMode == 2) {
                this.autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }
        //end 

        boolean hasInstAwareBpps = this.hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = mbd.getDependencyCheck() != 0;
        PropertyDescriptor[] filteredPds = null;
        if (hasInstAwareBpps) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }

            //属性赋值后,判断是否有InstantiationAwareBeanPostProcessor实例,有的话从缓存集合中获取遍历
            Iterator var9 = this.getBeanPostProcessors().iterator();

            while(var9.hasNext()) {
                BeanPostProcessor bp = (BeanPostProcessor)var9.next();
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor)bp;
                    //逐个调用其postProcessProperties方法
                    PropertyValues pvsToUse = ibp.postProcessProperties((PropertyValues)pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        if (filteredPds == null) {
                            filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
//逐个调用其postProcessPropertyValues方法
                        pvsToUse = ibp.postProcessPropertyValues((PropertyValues)pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }

                    pvs = pvsToUse;
                }
            }
        }

        if (needsDepCheck) {
            if (filteredPds == null) {
                filteredPds = this.filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }

            this.checkDependencies(beanName, mbd, filteredPds, (PropertyValues)pvs);
        }

        if (pvs != null) {
            this.applyPropertyValues(beanName, mbd, bw, (PropertyValues)pvs);
        }

    }
}

接着查看initializeBean方法源码:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(() -> {
            this.invokeAwareMethods(beanName, bean);
            return null;
        }, this.getAccessControlContext());
    } else {
        this.invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        //执行PostProcessorsBeforeInitialization
        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
    }

    try {
        this.invokeInitMethods(beanName, wrappedBean, mbd);
    } catch (Throwable var6) {
        throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
    }

    if (mbd == null || !mbd.isSynthetic()) {
        //执行PostProcessorsAfterInitialization
        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

至此我们通过查看Bean生命周期相关源码弄清楚了BeanPostProcessor和InstantiationAwareBeanPostProcessor相关方法的执行时机以及原理。

上面源码的追踪其实不仅涉及到了BeanPostProcessor和InstantiationAwareBeanPostProcessor相关方法的执行时机以及原理,更是整个Bean生命周期创建过程。

3. 总结

下面通过一张流程图总结本文:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/851575.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号