美文网首页
BeanFactoryPostProcessor和BeanPos

BeanFactoryPostProcessor和BeanPos

作者: zhengaoly | 来源:发表于2022-03-02 11:26 被阅读0次

    BeanFactoryPostProcessor和BeanPostProcessor

    BeanFactoryPostProcessor:BeanFactory 后置处理器,是对 BeanDefinition 对象进行修改。(BeanDefinition:存储 bean 标签的信息,用来生成 bean 实例)
    BeanPostProcessor:Bean 后置处理器,是对生成的 Bean 对象进行修改。

    bean初始化流程

    配置类解析(在BeanFactoryPostProcessor中,属于BeanDefinitionRegistryPostProcessor类型的,这种类型会优先调用)->定义beandefinition->其他类型的BeanFactoryPostProcessor可以处理这些beandefinition,做一些hack操作->bean实例化(实例化:instantiation)->bean初始化(类似于@bean的init-method),初始化前后会调用BeanPostProcessor的两个方法

    一、BeanFactoryPostProcessor

    该接口源码如下:

    public interface BeanFactoryPostProcessor {
    
        //可以通过beanFactory获取bean定义信息
        void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
    
    }
    

    BeanFactoryPostProcessor 接口是针对 bean 容器的,它的实现类可以在当前 BeanFactory 初始化(spring 容器加载 bean 定义文件)后,bean 实例化之前修改 bean 的定义属性,达到影响之后实例化 bean 的效果。
    也就是说,Spring 允许 BeanFactoryPostProcessor 在容器实例化任何其它 bean 之前读取配置元数据,并可以根据需要进行修改,例如可以把 bean 的 scope 从 singleton 改为 prototype,也可以把 property 的值给修改掉。可以同时配置多个 BeanFactoryPostProcessor,并通过设置’order’属性来控制各个 BeanFactoryPostProcessor 的执行次序。
    spring 中内置了一些 BeanFactoryPostProcessor 接口实现类,如下所示:

    img

    二、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;
        }
    }
    

    BeanPostProcessor 能在 spring 容器实例化 bean 之后,在执行 bean 的初始化方法前后,添加一些自己的处理逻辑。初始化方法包括以下两种:

    1、实现 InitializingBean 接口的 bean,对应方法为 afterPropertiesSet
    2、xml 定义中,通过 init-method 设置的方法

    BeanPostProcessor 是 BeanFactoryPostProcessor 之后执行的。
    spring 中内置了一些 BeanPostProcessor 接口实现类,如下所示:

    img

    如果自定义了多个的 BeanPostProcessor 的实现类,通过实现 Ordered 接口,设置 order 属性,可以按照顺序执行实现类的方法。

    实际上,org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors在调用beanfactiorypostProcessor时,内部会调用所有的beanfactiorypostProcessor,根据类型进行分批调用,先调用BeanDefinitionRegistryPostProcessor类型的后置处理器,进行配置类解析,在调用其他后置处理器,而且处理器可以通过@order进行排序.参见方法org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)的内部实现.

    三、例子

    (链接:https://blog.csdn.net/caihaijiang/article/details/35552859
    1、bean 的定义

    public class CustomBean implements InitializingBean {
        private String desc;
        private String remark;
    
        public CustomBean() {
            System.out.println("第二步:执行CustomBean类的无参构造函数");
        }
        public String getDesc() {
            return desc;
        }
        public void setDesc(String desc) {
            System.out.println("第三步:调用setDesc方法");
            this.desc = desc;
        }
        public String getRemark() {
            return remark;
        }
        public void setRemark(String remark) {
            System.out.println("第四步:调用setRemark方法");
            this.remark = remark;
        }
        public void afterPropertiesSet() throws Exception {
            System.out.println("第六步:调用afterPropertiesSet方法");
            this.desc = "在初始化方法中修改之后的描述信息";
        }
        public void initMethod() {
            System.out.println("第七步:调用initMethod方法");
        }
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("[描述:").append(desc);
            builder.append(", 备注:").append(remark).append("]");
            return builder.toString();
        }
    }
    

    2、定义 BeanFactoryPostProcessor

    public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            System.out.println("第一步:调用MyBeanFactoryPostProcessor的postProcessBeanFactory");
            BeanDefinition bd = beanFactory.getBeanDefinition("customBean");
            MutablePropertyValues pv =  bd.getPropertyValues();
            if (pv.contains("remark")) {
                pv.addPropertyValue("remark", "在BeanFactoryPostProcessor中修改之后的备忘信息");
            }
        }
    
    }
    

    3、定义 BeanPostProcessor

    public class MyBeanPostProcessor implements BeanPostProcessor {
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("第五步:BeanPostProcessor,对象" + beanName + "调用初始化方法之前的数据: " + bean.toString());
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("第八步:BeanPostProcessor,对象" + beanName + "调用初始化方法之后的数据:" + bean.toString());
            return bean;
        }
    }
    

    4、定义测试类

    public class PostProcessorTest {
            public static void main(String[] args) {
                ApplicationContext context = new ClassPathXmlApplicationContext("spring/postprocessor.xml");
                CustomBean bean = (CustomBean) context.getBean("customBean");
                System.out.println("################ 实例化、初始化bean完成");
                System.out.println("****************下面输出结果");
                System.out.println("描述:" + bean.getDesc());
                System.out.println("备注:" + bean.getRemark());
    
            }
    }
    

    运行结果如下:

    第一步:调用MyBeanFactoryPostProcessor的postProcessBeanFactory
    第二步:执行CustomBean类的无参构造函数
    第三步:调用setDesc方法
    第四步:调用setRemark方法
    第五步:BeanPostProcessor,对象customBean调用初始化方法之前的数据: [描述:原始的描述信息, 备注:在BeanFactoryPostProcessor中修改之后的备忘信息]
    第六步:调用afterPropertiesSet方法
    第七步:调用initMethod方法
    第八步:BeanPostProcessor,对象customBean调用初始化方法之后的数据:[描述:在初始化方法中修改之后的描述信息, 备注:在BeanFactoryPostProcessor中修改之后的备忘信息]
    ################ 实例化、初始化bean完成
    ****************下面输出结果
    描述:在初始化方法中修改之后的描述信息
    备注:在BeanFactoryPostProcessor中修改之后的备忘信息
    
    *************************************************************************
    分析以上结果:在bean实例化之前,首先执行BeanFactoryPostProcessor实现类的方法,然后通过调用bean的无参构造函数实例化bean,并调用set方法注入属性值。bean实例化后,执行初始化操作,调用两个初始化方法(两个初始化方法的顺序:先执行afterPropertiesSet,再执行init-method)前后,执行了BeanPostProcessor实现类的两个方法。
    
    

    四 、注意事项

    不要在BeanFactoryPostProcessor中获取bean对象,会导致bean的过早实例化,导致后续无法进行依赖注入.

    参考:使用BeanFactoryPostProcessor——这种姿势不要用

    相关文章

      网友评论

          本文标题:BeanFactoryPostProcessor和BeanPos

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