最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Spring IOC官方文档学习笔记(八)之容器扩展点

来源:博客园


(资料图)

1.通过BeanPostProcessor来自定义bean

(1) BeanPostProcessor用于在容器完成了对bean的实例化,配置及初始化后来实现一些自定义逻辑,它是用于操纵由容器创建的每个bean实例的,即在容器实例化了一个bean后以及该bean的初始化回调(如InitializingBean.afterPropertiesSet()等)被执行之前,会将这个bean交由BeanPostProcessor来进行处理。通过BeanPostProcessor,我们可以对bean实例进行任何操作,包括忽略掉初始化回调等,BeanPostProcessor通常用来检查回调接口,或用来生成某个bean的代理对象,因此一些Spring AOP的基础类就被实现为BeanPostProcessor实例,以提供代理对象,如下是简单使用BeanPostProcessor的一个例子

//让ExampleA实现3个初始化回调public class ExampleA implements InitializingBean {    private String name;    public ExampleA() {        System.out.println("ExampleA的构造方法被调用");        System.out.println("----------------------------------------");    }    //这个方法只用于IOC的属性注入    public void setName(String name) {        System.out.println("IOC对ExampleA的name属性进行注入,值为:" + name);        System.out.println("----------------------------------------");        this.name = name;    }        //这个方法用于我们自己手动注入    public void setNameInOtherWay(String name) {        this.name = name;    }    public String getName() {        return name;    }    @Override    public String toString() {        return "ExampleA{" +                "name="" + name + "\"" +                "}";    }    @PostConstruct    public void postConstruct() {        System.out.println("正在执行初始化回调PostConstruct,此时的ExampleA为:" + this);        this.setNameInOtherWay("zzz2");        System.out.println("执行完毕,此时的ExampleA为:" + this);        System.out.println("----------------------------------------");    }    @Override    public void afterPropertiesSet() throws Exception {        System.out.println("正在执行初始化回调InitializingBean.afterPropertiesSet,此时的ExampleA为:" + this);        this.setNameInOtherWay("zzz3");        System.out.println("执行完毕,此时的ExampleA为:" + this);        System.out.println("----------------------------------------");    }    public void init() {        System.out.println("正在执行初始化回调init-method,此时的ExampleA为:" + this);        this.setNameInOtherWay("zzz4");        System.out.println("执行完毕,此时的ExampleA为:" + this);        System.out.println("----------------------------------------");    }}//实现BeanPostProcessor,自定义后置处理器来操纵bean实例(注意:需要把我们的自定义处理器注入到容器中),它主要提供了2个方法public class Processor implements BeanPostProcessor {    /**     * 该方法作用于bean实例创建配置好后,初始化回调执行前,来自定义一些逻辑     * @param bean 实例化并配置好后的bean     * @param beanName  bean的名称     * @return  自定义操作完成后的bean     * @throws BeansException     */    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("正在执行postProcessBeforeInitialization,此时的ExampleA为:" + bean);        ((ExampleA) bean).setNameInOtherWay("zzz1");        System.out.println("执行完毕,此时的ExampleA为:" + bean);        System.out.println("----------------------------------------");        return bean;    }        /**     * 该方法作用于初始化回调执行后     */    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("正在执行postProcessAfterInitialization,此时的ExampleA为:" + bean);        ((ExampleA) bean).setNameInOtherWay("zzz5");        System.out.println("执行完毕,此时的ExampleA为:" + bean);        System.out.println("----------------------------------------");        return bean;    }}                                        //启动容器后,打印结果为ExampleA的构造方法被调用----------------------------------------IOC对ExampleA的name属性进行注入,值为:zzz----------------------------------------正在执行postProcessBeforeInitialization,此时的ExampleA为:ExampleA{name="zzz"}执行完毕,此时的ExampleA为:ExampleA{name="zzz1"}----------------------------------------正在执行初始化回调PostConstruct,此时的ExampleA为:ExampleA{name="zzz1"}执行完毕,此时的ExampleA为:ExampleA{name="zzz2"}----------------------------------------正在执行初始化回调InitializingBean.afterPropertiesSet,此时的ExampleA为:ExampleA{name="zzz2"}执行完毕,此时的ExampleA为:ExampleA{name="zzz3"}----------------------------------------正在执行初始化回调init-method,此时的ExampleA为:ExampleA{name="zzz3"}执行完毕,此时的ExampleA为:ExampleA{name="zzz4"}----------------------------------------正在执行postProcessAfterInitialization,此时的ExampleA为:ExampleA{name="zzz4"}执行完毕,此时的ExampleA为:ExampleA{name="zzz5"}----------------------------------------

综上可见,添加了BeanPostProcessor后,bean的初始化流程为:执行bean的构造函数 -> IOC进行属性注入 -> BeanPostProcessor.postProcessBeforeInitialization -> 三大初始化回调 -> BeanPostProcessor.postProcessAfterInitialization

(2) 我们可以向容器中注入多个自定义BeanPostProcessor,并通过实现Ordered接口来控制这些BeanPostProcessor的执行顺序,如下所示

public class ExampleA { }//让该自定义后置处理器实现Ordered接口,指定它在所有自定义后置处理器中的执行顺序public class Processor0 implements BeanPostProcessor, Ordered {    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("Order值为0的postProcessBeforeInitialization执行...");        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("Order值为0的postProcessAfterInitialization执行...");        return bean;    }    @Override    public int getOrder() {        return 0;    }}public class Processor1 implements BeanPostProcessor, Ordered {    @Override    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        System.out.println("Order值为1的postProcessBeforeInitialization执行...");        return bean;    }    @Override    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        System.out.println("Order值为1的postProcessAfterInitialization执行...");        return bean;    }    @Override    public int getOrder() {        return 1;    }}            //启动容器,输出如下Order值为0的postProcessBeforeInitialization执行...Order值为1的postProcessBeforeInitialization执行...Order值为0的postProcessAfterInitialization执行...Order值为1的postProcessAfterInitialization执行...

由上可见,getOrder返回值越小,自定义的后置处理器就越先执行

(3) 在一个容器中注入了一个BeanPostProcessor,那么该BeanPostProcessor仅对该容器中的bean进行后置处理,例如,即父容器中的BeanPostProcessor不会作用于子容器中的bean

(4) BeanPostProcessor作用于bean实例化并配置好了之后,换句话说,在BeanPostProcessor起作用时,bean实例已经存在了,因此,如果我们想要修改bean的配置元数据(即BeanDefinition,此时的bean还未被创建),则需要实现BeanFactoryPostProcessor接口,它与BeanPostProcessor类似,只不过作用时机不同

未完待续...

关键词: 正在执行 执行完毕 后置处理器