InstantiationAwareBeanPostProcessor 接口继承了 BeanPostProcessor 接口。
BeanPostProcessor 主要是在 Bean 调用初始化方法前后进行拦截。
而 InstantiationAwareBeanPostProcessor 接口在 BeanPostProcessor 基础上添加了对 bean 的创建前后,以及设置属性前进行拦截。
它的方法如下:

方法执行顺序备注
postProcessBeforeInstantiation()在 Bean 创建前调用可用于创建代理类,如果返回的不是 null(也就是返回的是一个代理类) ,那么后续只会调用 postProcessAfterInitialization() 方法
postProcessAfterInstantiation()在 Bean 创建后调用返回值会影响 postProcessProperties() 是否执行,其中返回 false 的话,是不会执行。
postProcessProperties()在 Bean 设置属性前调用用于修改 bean 的属性,如果返回值不为空,那么会更改指定字段的值
postProcessBeforeInitialization()在 Bean 调用初始化方法前调用允许去修改 bean 实例化后,没有调用初始化方法前状态的属性
postProcessAfterInitialization()在 Bean 调用初始化方法后调用允许去修改 bean 调用初始化方法后状态的属性

验证

TestBean 类

public class TestBean implements InitializingBean {
    protected Object field;

    public TestBean() {
        System.out.println("创建 TestBean 对象");
    }

    public Object getField() {
        return field;
    }

    public void setField(Object field) {
        System.out.println("设置 field 属性");
        this.field = field;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("调用初始化方法");
    }

    @Override
    public String toString() {
        return "TestBean{" +
                "field=" + field +
                '}';
    }
}

InstantiationAwareBeanPostProcessor 类

/**
* InstantiationAwareBeanPostProcessor 的实现类
*/
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if(isMatchClass(beanClass)){
            System.out.println("调用 postProcessBeforeInstantiation 方法");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if(isMatchClass(bean.getClass())){
            System.out.println("调用 postProcessAfterInstantiation 方法");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if(isMatchClass(bean.getClass())){
            System.out.println("调用 postProcessProperties 方法");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if(isMatchClass(bean.getClass())){
            System.out.println("调用 postProcessBeforeInitialization 方法");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(isMatchClass(bean.getClass())){
            System.out.println("调用 postProcessAfterInitialization 方法");
        }
        return bean;
    }

    private boolean isMatchClass(Class<?> beanClass){
        // ClassUtils 类为 org.springframework.util.ClassUtils
        return TestBean.class.equals(ClassUtils.getUserClass(beanClass));
    }
}

测试类

@SpringBootTest
public class CustomProcessorTest {
    @Autowired
    private ApplicationContext applicationContext;

    @Test
    void test(){
        TestBean testBean = applicationContext.getBean(TestBean.class);
        System.out.println(testBean);
    }

    /**
     * 创建 TestBean 和 CustomInstantiationAwareBeanPostProcessor 这2个 bean
     */
    @TestConfiguration
    static class TestConfig{
        @Bean
        public TestBean getTestBean(){
            TestBean testBean = new TestBean();
            testBean.setField("1");
            return testBean;
        }

        @Bean
        public CustomInstantiationAwareBeanPostProcessor customInstantiationAwareBeanPostProcessor(){
            return new CustomInstantiationAwareBeanPostProcessor();
        }
    }
}

执行结果

调用 postProcessBeforeInstantiation 方法
创建 TestBean 对象
设置 field 属性
调用 postProcessAfterInstantiation 方法
调用 postProcessProperties 方法
调用 postProcessBeforeInitialization 方法
调用初始化方法
调用 postProcessAfterInitialization 方法
TestBean{field=1}

分析方法

1. postProcessBeforeInstantiation()

postProcessBeforeInstantiation() 方法是在 Bean 创建之前调用的,该方法允许我们返回 Bean 的其他子类(我们也可以用 cglib 返回一个代理对象)。
这个方法在 InstantiationAwareBeanPostProcessor 接口的默认实现是返回 null。

结论

如果 postProcessBeforeInstantiation() 返回的不是 null ,那么 Spring 只会在 Bean 创建的时候,
只调用 postProcessBeforeInstantiation() 和 postProcessAfterInitialization() 方法。

验证

修改 CustomInstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation() 方法:

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    if (isMatchClass(beanClass)) {
        System.out.println("调用 postProcessBeforeInstantiation 方法");
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(beanClass);
        enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
            System.out.println("目标方法执行前:" + method);
            Object object = proxy.invokeSuper(obj, args);
            System.out.println("目标方法执行后:" + method);
            return object;
        });
        return enhancer.create();
    }
    return null;
}

执行结果:

调用 postProcessBeforeInstantiation 方法
创建 TestBean 对象
调用 postProcessAfterInitialization 方法
目标方法执行前:public java.lang.String TestBean.toString()
目标方法执行后:public java.lang.String TestBean.toString()
TestBean{field=null}

从执行结果中看,Spring 容器只执行了 postProcessBeforeInstantiation() 和 postProcessAfterInitialization() 方法,CustomInstantiationAwareBeanPostProcessor 其余的方法均不执行。
也没有执行 TestBean 的 setField() 和 afterPropertiesSet() 方法。

原因

从 Spring 创建 Bean 的过程中入手, Spring 在创建 Bean 时,会调用 AbstractAutowireCapableBeanFactory 的 createBean() 方法:

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    // 省略上面的方法
    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    // 省略下面的方法
}

从 createBean() 的代码片段中,它先去调用 resolveBeforeInstantiation() 方法来尝试获取代理类,如果获取到了,就直接返回该代理类。
否则就去调用 doCreateBean() 方法,以创建 bean 的实例,并且返回。

resolveBeforeInstantiation() 方法以及调用到的关联方法:
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
    for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
        // 这里会遍历每一个 InstantiationAwareBeanPostProcessor 的子类,所以 InstantiationAwareBeanPostProcessor 的子类顺序很重要
        Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
        // 如果返回的不为 null ,后面的所有 InstantiationAwareBeanPostProcessor 的子类就跳过执行了
        if (result != null) {
            return result;
        }
    }
    return null;
}

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        // 这里会遍历每一个 BeanPostProcessor 的子类,所以 BeanPostProcessor 的子类顺序很重要
        Object current = processor.postProcessAfterInitialization(result, beanName);
        // 如果返回的为 null ,后面的所有 BeanPostProcessor 的子类就跳过执行了
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

从 resolveBeforeInstantiation() 方法的代码片段中,它的逻辑基本是这样:

  1. 遍历所有的 InstantiationAwareBeanPostProcessor 实现类,调用其 postProcessBeforeInstantiation() 方法。
  2. 如果 postProcessBeforeInstantiation() 方法返回值,那么就表示找到了代理类,那么就会结束遍历
  3. 如果步骤2没有找到代理类,那么 resolveBeforeInstantiation() 方法就基本执行结束,返回 null 值。
  4. 如果步骤2找到了代理类,就会遍历所有 BeanPostProcessor 的实现类,调用其 postProcessAfterInitialization() 方法。
  5. 如果 postProcessAfterInitialization() 方法返回的是 null , 那么就返回上一次遍历得到的结果,或者是代理类本身。

2. postProcessAfterInstantiation()

postProcessAfterInstantiation() 方法的返回值会影响 postProcessProperties() 是否会执行:

  • false :不会执行
  • true :执行

原因

上面已经提及了 Spring 创建 Bean 是会调用 createBean() 方法,其中如果 postProcessBeforeInstantiation() 返回的值为 null 的话,就会执行 doCreateBean() 方法。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    // 忽略上面代码
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    // 忽略下面代码
}

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // 忽略上面代码
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // 遍历所有 InstantiationAwareBeanPostProcessor ,并调用其 postProcessAfterInstantiation() 方法,如果返回 false ,就不会执行后续步骤了。
            if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                return;
            }
        }
    }
    // 忽略中间部分代码
    if (hasInstantiationAwareBeanPostProcessors()) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // 遍历所有 InstantiationAwareBeanPostProcessor ,并调用其 postProcessProperties() 方法,如果存在返回的值为 null ,就不会执行后续步骤了
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                return;
            }
            pvs = pvsToUse;
        }
    }

    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
    if (needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    if (pvs != null) {
        // 根据调用所有 InstantiationAwareBeanPostProcessor 的 postProcessProperties() 方法所得到的值,来修改这个 bean 的属性
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

从上面的代码片段中,doCreateBean() 方法会调用 populateBean() 方法,其中 populateBean() 方法它的主要逻辑是:

  1. 遍历所有 InstantiationAwareBeanPostProcessor ,调用 postProcessAfterInstantiation() 方法,如果返回值为 false 了,就不会执行后续步骤了
  2. 遍历所有 InstantiationAwareBeanPostProcessor ,调用 postProcessProperties() 方法,如果返回值为 null ,就不会执行后续的其他步骤了
  3. 如果 pvs 的值不为空,那么就去调用 applyPropertyValues() 方法来设置 bean 的属性

3. postProcessProperties()

postProcessProperties() 方法返回的 PropertyValues 会影响 bean 属性的设置。

结论

如果 PropertyValues 为 null ,PropertyValues 里面没有数据,就不会对 bean 的属性做任何修改。
否则,就会修改 Bean 的属性值。

验证

修改 CustomInstantiationAwareBeanPostProcessor 类的 postProcessProperties() 方法逻辑:

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
    if (isMatchClass(bean.getClass())) {
        System.out.println("调用 postProcessProperties 方法");
        MutablePropertyValues mpvs = (MutablePropertyValues) pvs;
        // 这里修改 TestBean 的 field 字段值为 "update value"
        mpvs.add("field","update value");
    }
    return pvs;
}

输出结果:

调用 postProcessBeforeInstantiation 方法
创建 TestBean 对象
设置 field 属性
调用 postProcessAfterInstantiation 方法
调用 postProcessProperties 方法
设置 field 属性
调用 postProcessBeforeInitialization 方法
调用初始化方法
调用 postProcessAfterInitialization 方法
TestBean{field=update value}

4. postProcessBeforeInitialization() 和 postProcessAfterInitialization()

postProcessBeforeInitialization() 和 postProcessAfterInitialization() 这2个方法是在 Bean 的属性设置完之后执行的,可以通过这2个方法来完成对 Bean 的属性进行修改。
当 Spring 在 AbstractAutowireCapableBeanFactory 的 doCreateBean() 方法中调用完了 populateBean() 的方法后,就会调用 initializeBean() 方法。
故 initializeBean() 方法是 Spring 调用 postProcessBeforeInitialization() 和 postProcessAfterInitialization() 的主要逻辑:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    invokeAwareMethods(beanName, bean);

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 遍历所有 BeanPostProcessor 的子类,并调用 postProcessBeforeInitialization() 的方法
        // 如果 postProcessBeforeInitialization() 返回 null ,则返回上一个 BeanPostProcessor 子类返回的对象,
        // 或者是 bean 对象本身(如果调用第一个 BeanPostProcessor 子类就返回 null 的话)  
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 调用 bean 指定的 init 方法,或者是实现 InitializingBean 的 afterPropertiesSet() 方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null), beanName, ex.getMessage(), ex);
    }
    if (mbd == null || !mbd.isSynthetic()) {
        // 遍历所有 BeanPostProcessor 的子类,并调用 postProcessAfterInitialization() 的方法
        // 如果 postProcessAfterInitialization() 返回 null ,则返回上一个 BeanPostProcessor 子类返回的对象,
        // 或者是 bean 对象本身(如果调用第一个 BeanPostProcessor 子类就返回 null 的话)  
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}

参考博客/论坛

  1. Spring Boot –如何初始化Bean进行测试
  2. Spring之InstantiationAwareBeanPostProcessor接口介绍
  3. How to get a bean real class instead CGlib proxy?

yosoro
1 声望0 粉丝

this guy is lazy , nothing to write down