关于spring:Spring-学习笔记InstantiationAwareBeanPostProcessor接口

3次阅读

共计 11543 个字符,预计需要花费 29 分钟才能阅读完成。

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?
正文完
 0