美文网首页
Spring源码解析(十四)-BeanPostProcessor

Spring源码解析(十四)-BeanPostProcessor

作者: 秋水畏寒 | 来源:发表于2020-05-26 22:06 被阅读0次

Spring版本

5.2.5.RELEASE

参考

《芋道源码》

源码解读

在bean的创建流程中,可以看到诸多BeanPostProcessor的诸多应用,那么,BeanPostProcessor究竟是个怎样的神奇的存在呢?

BeanPostProcessor

public interface BeanPostProcessor {

    /**
     * Apply this {@code BeanPostProcessor} to the given new bean instance <i>before</i> any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * <p>The default implementation returns the given {@code bean} as-is.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     */
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     * Apply this {@code BeanPostProcessor} to the given new bean instance <i>after</i> any bean
     * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
     * or a custom init-method). The bean will already be populated with property values.
     * The returned bean instance may be a wrapper around the original.
     * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
     * instance and the objects created by the FactoryBean (as of Spring 2.0). The
     * post-processor can decide whether to apply to either the FactoryBean or created
     * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
     * <p>This callback will also be invoked after a short-circuiting triggered by a
     * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
     * in contrast to all other {@code BeanPostProcessor} callbacks.
     * <p>The default implementation returns the given {@code bean} as-is.
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return the bean instance to use, either the original or a wrapped one;
     * if {@code null}, no subsequent BeanPostProcessors will be invoked
     * @throws org.springframework.beans.BeansException in case of errors
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.FactoryBean
     */
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

通过源码注释可以看到,postProcessBeforeInitialization提供了一个途径去修改一个已经实例化的bean,但这个修改是发生在填充属性之后初始化bean之前的,而返回值则可能是一个对原始bean进行过包装后的bean。
postProcessBeforeInitialization不同的是,postProcessAfterInitialization发生在填充属性之后且初始化bean之后。
俩者的不同点在于是否初始化bean,这从方法名上其实也可以看出来,下面,通过demo具体演示一下如何通过BeanPostProcessor修改bean的属性

Demo

Student

public class Student {

    private String id;

    private String name;

    private String desc;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

BeanProcessorsTest

public class BeanProcessorsTest implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization");
        if (bean instanceof Student) {
            ((Student) bean).setId("id set by postProcessBeforeInitialization");
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization");
        if (bean instanceof Student) {
            ((Student) bean).setName("name set by postProcessAfterInitialization");
        }
        return bean;
    }

}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="beanProcessorsTest" class="com.kungyu.custom.element.BeanProcessorsTest"/>

    <bean id="student" class="com.kungyu.custom.element.Student">
        <property name="name" value="name"/>
        <property name="id" value="id"/>
    </bean>
</beans>

测试

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        BeanProcessorsTest beanProcessorsTest = (BeanProcessorsTest) context.getBean("beanProcessorsTest");

        Student student = (Student) context.getBean("student");
        System.out.println(student.getName());
        System.out.println(student.getId());

    }
}

结果

结果

可以看到,在spring.xml文件中设置的idname俩者的初始值已经被覆盖成BeanProcessorsTest中设置的值

相关文章

网友评论

      本文标题:Spring源码解析(十四)-BeanPostProcessor

      本文链接:https://www.haomeiwen.com/subject/hvdbahtx.html