Spring中的后置处理器BeanPostProcessor详解

 更新时间:2019年08月06日 16:33:42   作者:情陌人灬已不在  
这篇文章主要介绍了Spring中的后置处理器BeanPostProcessor详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

BeanPostProcessor接口作用:

如果我们想在Spring容器中完成bean实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个BeanPostProcessor接口实现类,然后注册到Spring IoC容器中。

package com.test.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * bean后置处理器
 * @author zss
 *
 */
public class PostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessBeforeInitialization(Object bean,
      String beanName) throws BeansException {
    if ("narCodeService".equals(beanName)) {//过滤掉bean实例ID为narCodeService
      return bean;
    }
    System.out.println("后置处理器处理bean=【"+beanName+"】开始");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return bean;
  }
  @Override
  public Object postProcessAfterInitialization(Object bean,
      String beanName) throws BeansException {
    if ("narCodeService".equals(beanName)) {
      return bean;
    }
    System.out.println("后置处理器处理bean=【"+beanName+"】完毕!");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return bean;
  }
}

注意:接口中两个方法不能返回null,如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象,因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中!

将Spring的后置处理器PostProcessor配置到Spring配置文件中

<?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 -->
   <bean id="narCodeService" class="com.test.service.impl.NarCodeServiceImpl">
   </bean>
  <bean id="beanLifecycle" class="com.test.spring.BeanLifecycle" init-method="init" destroy-method="close">
    <property name="name" value="张三"></property>
    <property name="sex" value="男"></property>
  </bean>
  <!-- Spring后置处理器 -->
  <bean id="postProcessor" class="com.test.spring.PostProcessor"/>
</beans>

BeanPostProcessor API:

public interface BeanPostProcessor {  
  //实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务 
  Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;    
  //实例化、依赖注入、初始化完毕时执行 
  Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; 
}

由API可以看出:

1:后置处理器的postProcessorBeforeInitailization方法是在bean实例化,依赖注入之后及自定义初始化方法(例如:配置文件中bean标签添加init-method属性指定Java类中初始化方法、
@PostConstruct注解指定初始化方法,Java类实现InitailztingBean接口)之前调用

2:后置处理器的postProcessorAfterInitailization方法是在bean实例化、依赖注入及自定义初始化方法之后调用

注意:

1.BeanFactory和ApplicationContext两个容器对待bean的后置处理器稍微有些不同。ApplicationContext容器会自动检测Spring配置文件中那些bean所对应的Java类实现了BeanPostProcessor
接口,并自动把它们注册为后置处理器。在创建bean过程中调用它们,所以部署一个后置处理器跟普通的bean没有什么太大区别。

2.BeanFactory容器注册bean后置处理器时必须通过代码显示的注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法

void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

Spring如何调用多个BeanPostProcessor实现类:

我们可以在Spring配置文件中添加多个BeanPostProcessor(后置处理器)接口实现类,在默认情况下Spring容器会根据后置处理器的定义顺序来依次调用。

Spring配置文件:

<?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定义 -->  
  <bean id="narCodeService" class="com.test.service.impl.NarCodeServiceImpl">
  </bean>
  <bean id="postProcessor" class="com.test.spring.PostProcessor"/>
  <bean id="postProcessorB" class="com.test.spring.PostProcessorB"/>
</beans>

BeanPostProcessor实现类:

package com.test.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
 * bean后置处理器
 * @author zss
 *
 */
public class PostProcessor implements BeanPostProcessor {

  @Override
  public Object postProcessBeforeInitialization(Object bean,
      String beanName) throws BeansException {
    System.out.println("后置处理器处理bean=【"+beanName+"】开始");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean,
      String beanName) throws BeansException {
    System.out.println("后置处理器处理bean=【"+beanName+"】完毕!");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return bean;
  }
}
----------------------------------------------------------------------------------------------------------------------------------------
package com.test.spring;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class PostProcessorB implements BeanPostProcessor {
  @Override
  public Object postProcessBeforeInitialization(Object bean,
      String beanName) throws BeansException {
    System.out.println("后置处理器开始调用了");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return bean;
  }

  @Override
  public Object postProcessAfterInitialization(Object bean,
      String beanName) throws BeansException {
    System.out.println("后置处理器调用结束了");
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return bean;
  }
}

Test case:

package com.test.spring;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class T {
  AbstractApplicationContext applicationcontext=null;
  @Before
  public void before() {
    System.out.println("》》》Spring ApplicationContext容器开始初始化了......");
    applicationcontext= new ClassPathXmlApplicationContext(new String[]{"test1-service.xml"});
    System.out.println("》》》Spring ApplicationContext容器初始化完毕了......");
  }
  @Test
  public void test() {
    applicationcontext.registerShutdownHook();  
  }
}

测试结果:

》》》Spring ApplicationContext容器开始初始化了......
2017-03-19 10:50:29 INFO:ClassPathXmlApplicationContext-Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@18c92ff9: startup date [Sun Mar 19 10:50:29 CST 2017]; root of context hierarchy
2017-03-19 10:50:29 INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]
后置处理器处理bean=【narCodeService】开始
后置处理器开始调用了
后置处理器处理bean=【narCodeService】完毕!
后置处理器调用结束了
》》》Spring ApplicationContext容器初始化完毕了......
2017-03-19 10:50:34 INFO:ClassPathXmlApplicationContext-Closing org.springframework.context.support.ClassPathXmlApplicationContext@18c92ff9: startup date [Sun Mar 19 10:50:29 CST 2017]; root of context hierarchy

在Spring机制中可以指定后置处理器调用顺序,通过让BeanPostProcessor接口实现类实现Ordered接口getOrder方法,该方法返回一整数,默认值为 0,优先级最高,值越大优先级越低

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot整合rabbitMq自定义消息转换方式

    SpringBoot整合rabbitMq自定义消息转换方式

    这篇文章主要介绍了SpringBoot整合rabbitMq自定义消息转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Java并发之嵌套管程锁死详解

    Java并发之嵌套管程锁死详解

    这篇文章主要介绍了Java并发之嵌套管程锁死详解,涉及嵌套管程锁死的发生,实例等相关内容,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • mybatis insert返回主键代码实例

    mybatis insert返回主键代码实例

    这篇文章主要介绍了mybatis insert返回主键代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • 哲学家就餐问题中的JAVA多线程学习

    哲学家就餐问题中的JAVA多线程学习

    哲学家就餐问题是1965年由Dijkstra提出的一种线程同步的问题,下面我们就看一下JAVA多线程如何做
    2013-11-11
  • SpringBoot3集成WebSocket的全过程

    SpringBoot3集成WebSocket的全过程

    WebSocket通过一个TCP连接在客户端和服务器之间建立一个全双工、双向的通信通道,使得客户端和服务器之间的数据交换变得更加简单,本文给大家介绍了SpringBoot3集成WebSocket的全过程,并有相关的代码示例供大家参考,需要的朋友可以参考下
    2024-05-05
  • Spring cloud alibaba之Ribbon负载均衡实现方案

    Spring cloud alibaba之Ribbon负载均衡实现方案

    Spring cloud Ribbon是基于Netflix Ribbon实现的一套客户端的负载均衡工具,Ribbon客户端提供一系列完善的配置,如超时、重试等,Ribbon也可以实现自己的负载均衡算法,感兴趣的朋友跟随小编一起看看吧
    2021-07-07
  • Java如何把map分割成多个map

    Java如何把map分割成多个map

    这篇文章主要介绍了Java如何把map分割成多个map,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-08-08
  • 使用@Autowired注解引入server服务层方法时报错的解决

    使用@Autowired注解引入server服务层方法时报错的解决

    这篇文章主要介绍了使用@Autowired注解引入server服务层方法时报错的解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • 18个Java8日期处理的实践(太有用了)

    18个Java8日期处理的实践(太有用了)

    这篇文章主要介绍了18个Java8日期处理的实践(太有用了),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • this关键字详解

    this关键字详解

    这篇文章主要介绍了this关键字,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03

最新评论