Spring之BeanPostProcessor(后置处理器)介绍

本文内容纲要:

- BeanPostProcessor

- 一、自定义后置处理器演示

- 1.自定义处理器

- 2.Pojo类

- 3.配置文件注册

- 4.测试

- 二、多个后置处理器

- 三、显示指定顺序

  为了弄清楚Spring框架,我们需要分别弄清楚相关核心接口的作用,本文来介绍下BeanPostProcessor接口

BeanPostProcessor

  该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。接口的源码如下

public interface BeanPostProcessor {

/**

* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean

* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}

* or a custom init-method). The bean will already be populated with property values.

* The returned bean instance may be a wrapper around the original.

* @param bean the new bean instance

* @param beanName the name of the bean

* @return the bean instance to use, either the original or a wrapped one;

* if {@code null}, no subsequent BeanPostProcessors will be invoked

* @throws org.springframework.beans.BeansException in case of errors

* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet

*/

Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

/**

* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean

* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}

* or a custom init-method). The bean will already be populated with property values.

* The returned bean instance may be a wrapper around the original.

* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean

* instance and the objects created by the FactoryBean (as of Spring 2.0). The

* post-processor can decide whether to apply to either the FactoryBean or created

* objects or both through corresponding {@code bean instanceof FactoryBean} checks.

* <p>This callback will also be invoked after a short-circuiting triggered by a

* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,

* in contrast to all other BeanPostProcessor callbacks.

* @param bean the new bean instance

* @param beanName the name of the bean

* @return the bean instance to use, either the original or a wrapped one;

* if {@code null}, no subsequent BeanPostProcessors will be invoked

* @throws org.springframework.beans.BeansException in case of errors

* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet

* @see org.springframework.beans.factory.FactoryBean

*/

Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

方法说明
postProcessBeforeInitialization实例化、依赖注入完毕,
在调用显示的初始化之前完成一些定制的初始化任务
postProcessAfterInitialization实例化、依赖注入、初始化完毕时执行

一、自定义后置处理器演示

1.自定义处理器

package com.dpb.processor;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.config.BeanPostProcessor;

/**

* 自定义BeanPostProcessor实现类

* BeanPostProcessor接口的作用是:

* 我们可以通过该接口中的方法在bean实例化、配置以及其他初始化方法前后添加一些我们自己的逻辑

* @author dengp

*

*/

public class MyBeanPostProcessor implements BeanPostProcessor{

/**

* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("before--实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

/**

* 实例化、依赖注入、初始化完毕时执行

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("after...实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

}

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

2.Pojo类

public class User {

private int id;

private String name;

private String beanName;

public User(){

System.out.println("User 被实例化");

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

System.out.println("设置:"+name);

this.name = name;

}

public String getBeanName() {

return beanName;

}

public void setBeanName(String beanName) {

this.beanName = beanName;

}

/**

* 自定义的初始化方法

*/

public void start(){

System.out.println("User 中自定义的初始化方法");

}

}

3.配置文件注册

<?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 class="com.dpb.pojo.User" id="user" init-method="start">

<property name="name" value="波波烤鸭" />

</bean>

<!-- 注册处理器 -->

<bean class="com.dpb.processor.MyBeanPostProcessor"></bean>

</beans>

4.测试

@Test

public void test() {

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

User user = ac.getBean(User.class);

System.out.println(user);

}

输出结果

User 被实例化

设置:波波烤鸭

before--实例化的bean对象:com.dpb.pojo.User@65e2dbf3 user

User 中自定义的初始化方法

after...实例化的bean对象:com.dpb.pojo.User@65e2dbf3 user

com.dpb.pojo.User@65e2dbf3

  通过输出语句我们也能看到postProcessBeforeInitialization方法的输出语句是在Bean实例化及属性注入后执行的,且在自定义的初始化方法之前执行(通过init-method指定)。而postProcessAfterInitialization方法是在自定义初始化方法执行之后执行的。

注意!!!

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

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

    /**

    • Add a new BeanPostProcessor that will get applied to beans created
    • by this factory. To be invoked during factory configuration.
    • Note: Post-processors submitted here will be applied in the order of

    • registration; any ordering semantics expressed through implementing the
    • {@link org.springframework.core.Ordered} interface will be ignored. Note
    • that autodetected post-processors (e.g. as beans in an ApplicationContext)
    • will always be applied after programmatically registered ones.
    • @param beanPostProcessor the post-processor to register

      */

      void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);

测试代码如下

@Test

public void test2() {

//ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));

// 显示添加后置处理器

bf.addBeanPostProcessor(bf.getBean(MyBeanPostProcessor.class));

User user = bf.getBean(User.class);

System.out.println(user);

}

二、多个后置处理器

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

public class MyBeanPostProcessor implements BeanPostProcessor{

/**

* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("A before--实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

/**

* 实例化、依赖注入、初始化完毕时执行

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("A after...实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

}

public class MyBeanPostProcessor2 implements BeanPostProcessor{

/**

* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("B before--实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

/**

* 实例化、依赖注入、初始化完毕时执行

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("B after...实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

}

配置文件注册

<?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 class="com.dpb.pojo.User" id="user" init-method="start">

<property name="name" value="波波烤鸭" />

</bean>

<!-- 注册处理器 -->

<bean class="com.dpb.processor.MyBeanPostProcessor"/>

<bean class="com.dpb.processor.MyBeanPostProcessor2"/>

</beans>

测试结果

User 被实例化

设置:波波烤鸭

A before--实例化的bean对象:com.dpb.pojo.User@7fac631b user

B before--实例化的bean对象:com.dpb.pojo.User@7fac631b user

User 中自定义的初始化方法

A after...实例化的bean对象:com.dpb.pojo.User@7fac631b user

B after...实例化的bean对象:com.dpb.pojo.User@7fac631b user

com.dpb.pojo.User@7fac631b

三、显示指定顺序

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

public class MyBeanPostProcessor implements BeanPostProcessor,Ordered{

/**

* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("A before--实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

/**

* 实例化、依赖注入、初始化完毕时执行

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("A after...实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

@Override

public int getOrder() {

// TODO Auto-generated method stub

return 10;

}

}

public class MyBeanPostProcessor2 implements BeanPostProcessor,Ordered{

/**

* 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

System.out.println("B before--实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

/**

* 实例化、依赖注入、初始化完毕时执行

* 注意:方法返回值不能为null

* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象

* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中

*/

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

System.out.println("B after...实例化的bean对象:"+bean+"\t"+beanName);

// 可以根据beanName不同执行不同的处理操作

return bean;

}

@Override

public int getOrder() {

// TODO Auto-generated method stub

return 2;

}

}

测试输出结果

User 被实例化

设置:波波烤鸭

B before--实例化的bean对象:com.dpb.pojo.User@7fac631b user

A before--实例化的bean对象:com.dpb.pojo.User@7fac631b user

User 中自定义的初始化方法

B after...实例化的bean对象:com.dpb.pojo.User@7fac631b user

A after...实例化的bean对象:com.dpb.pojo.User@7fac631b user

com.dpb.pojo.User@7fac631b

数值越大的优先级越低,所以A的输出就在后面了。

~好了通过本文详细大家对于BeanPostProcessor接口的作用应该比较清楚了。

本文内容总结:BeanPostProcessor,一、自定义后置处理器演示,1.自定义处理器,2.Pojo类,3.配置文件注册,4.测试,二、多个后置处理器,三、显示指定顺序,

原文链接:https://www.cnblogs.com/dengpengbo/p/10464892.html

以上是 Spring之BeanPostProcessor(后置处理器)介绍 的全部内容, 来源链接: utcz.com/z/362538.html

回到顶部