首页IT科技spring容器的加载方式(Spring IOC官方文档学习笔记(八)之容器扩展点)

spring容器的加载方式(Spring IOC官方文档学习笔记(八)之容器扩展点)

时间2025-06-15 03:00:22分类IT科技浏览4635
导读:1.通过BeanPostProcessor来自定义bean...

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; } } <!-- xml配置文件 --> <beans ....> <!-- 开启注解扫描                   ,否则PostConstruct注解不生效 --> <context:annotation-config></context:annotation-config> <bean id="exampleA" class="cn.example.spring.boke.ExampleA" init-method="init"> <property name="name" value="zzz"></property> </bean> <!-- 注意仅仅实现接口是不行的            ,我们必须把自定义后置处理器注册成bean      ,它才会生效 --> <bean id="processor" class="cn.example.spring.boke.Processor"></bean> </beans> //启动容器后                   ,打印结果为 ExampleA的构造方法被调用 ---------------------------------------- IOCExampleA的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; } } <!-- xml配置文件 --> <beans ....> <bean id="exampleA" class="cn.example.spring.boke.ExampleA"></bean> <bean id="processor0" class="cn.example.spring.boke.Processor0"></bean> <bean id="processor1" class="cn.example.spring.boke.Processor1"></bean> </beans> //启动容器      ,输出如下 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类似            ,只不过作用时机不同

未完待续...

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
仿真火车头模型专卖店(火车头伪原创插件-让你的文章更具独特性和可读性) 卸载了但是应用和功能里还有(为什么win10“添加或删除程序”列表留已卸载的程序名?)