spring的bean周期中BeanPostProcessor浅析

小咪咪 2022-04-17 03:28 257阅读 0赞

参考:https://www.cnblogs.com/sishang/p/6576665.html

   https://www.jianshu.com/p/890446a3d477

1. 基本概念

spring容器在实例化bean之后(通过构造器创建对象并注入属性值即为实例化),可以使用BeanPostProcessor接口在bean的初始化方法前后根据需要做自己的逻辑处理。

2. BeanPostProcessor后置处理器的使用

BeanPostProcessor接口有两个方法,postProcessBeforeInitialization和postProcessAfterInitialization,默认情况下后置处理器会处理容器中所有的bean。

postProcessBeforeInitialization在bean初始化方法之前调用,初始化方法包括:bean标签添加init-method属性指定Java类中初始化方法、 @PostConstruct注解指定初始化方法,Java类实现InitailztingBean接口所产生的afterPropertiesSet()方法等。

postProcessAfterInitialization在bean初始化方法之后调用。

  1. public class PostProcessor implements BeanPostProcessor {
  2. @Override
  3. public Object postProcessBeforeInitialization(Object bean,
  4. String beanName) throws BeansException {
  5. if ("narCodeService".equals(beanName)) {//此方法获取容器中所有的bean,根据 beanName 名称选择要处理的bean,此处过滤实例ID为narCodeService
  6. return bean;
  7. }
  8. System.out.println("后置处理器处理bean=【"+beanName+"】开始");
  9. try {
  10. Thread.sleep(1000);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }
  14. return bean;
  15. }
  16. @Override
  17. public Object postProcessAfterInitialization(Object bean,
  18. String beanName) throws BeansException {
  19. if ("narCodeService".equals(beanName)) {
  20. return bean;
  21. }
  22. System.out.println("后置处理器处理bean=【"+beanName+"】完毕!");
  23. try {
  24. Thread.sleep(1000);
  25. } catch (InterruptedException e) {
  26. e.printStackTrace();
  27. }
  28. return bean;
  29. }
  30. }

上段代码两个方法的第一个参数为bean对象,第二个参数为bean对象的全称名称(包名加类名)。然后该实现类配置在spring配置文件中就可以使用了。多个后置处理器按照配置顺序执行,可以配置order属性进行设置优先级。

然后将PostProcessor注入到spring容器中,比如配置到application.xml文件中。

下面有个完成实例:

  1. package renchaofeng;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.beans.factory.config.BeanPostProcessor;
  4. public class PostProcessor implements BeanPostProcessor {
  5. @Override
  6. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  7. if("messageService".equals(beanName)) {
  8. System.out.println("messageService init method after..");
  9. }
  10. if("testnreImpl".equals(beanName)) {
  11. System.out.println("testnreImpl init method after..");
  12. }
  13. return bean;
  14. }
  15. @Override
  16. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  17. if("messageService".equals(beanName)) {
  18. System.out.println("messageService init method before..");
  19. }
  20. if("testnreImpl".equals(beanName)) {
  21. System.out.println("testnreImpl init method before..");
  22. }
  23. return bean;
  24. }
  25. }

将 PostProcessor配置到spring容器中,

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
  5. <bean id="postProcessor" class="renchaofeng.PostProcessor"/>
  6. </beans>

分别定义两个接口和其实现类:

  1. package renchaofeng;
  2. public interface MessageService {
  3. String getMessage();
  4. }
  5. package renchaofeng;
  6. import org.springframework.beans.BeansException;
  7. import org.springframework.beans.factory.InitializingBean;
  8. import org.springframework.beans.factory.config.BeanPostProcessor;
  9. public class MessageServiceImpl implements MessageService,InitializingBean {
  10. public String getMessage() {
  11. return "hello world";
  12. }
  13. @Override
  14. public void afterPropertiesSet() throws Exception {
  15. System.out.println("message init method...");
  16. }
  17. }
  18. package renchaofeng;
  19. public interface Testnre {
  20. void getRen();
  21. }
  22. package renchaofeng;
  23. import org.springframework.beans.factory.InitializingBean;
  24. public class TestnreImpl implements Testnre,InitializingBean {
  25. @Override
  26. public void getRen() {
  27. System.out.println("fffff..");
  28. }
  29. @Override
  30. public void afterPropertiesSet() throws Exception {
  31. System.out.println("TestnreImpl init method..");
  32. }
  33. }

然后把上面两个实现类配置到spring容器中:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
  5. <bean id="messageService" class="renchaofeng.MessageServiceImpl"/>
  6. <bean id="postProcessor" class="renchaofeng.PostProcessor"/>
  7. <bean id="testnreImpl" class="renchaofeng.TestnreImpl"/>
  8. </beans>

写个测试类如下:

  1. package renchaofeng;
  2. import org.springframework.beans.BeansException;
  3. import org.springframework.context.ApplicationContext;
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;
  5. public class TestSpring {
  6. public static void main(String[] args) throws BeansException{
  7. ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring/application-ren.xml");
  8. System.out.println("context 启动成功");
  9. MessageService messageService = (MessageService)context.getBean("messageService");
  10. System.out.println(messageService.getMessage());
  11. }
  12. }

运行结果如下:

messageService init method before..
message init method…
messageService init method after..
testnreImpl init method before..
TestnreImpl init method..
testnreImpl init method after..
context 启动成功
hello world

说明每当一个bean执行初始化方法时,都会调用BeanPostProcessor的postProcessBeforeInitialization和postProcessAfterInitialization方法。

发表评论

表情:
评论列表 (有 0 条评论,257人围观)

还没有评论,来说两句吧...

相关阅读