柳州做网站优化/营销网站案例
为了弄清楚Spring框架,我们需要分别弄清楚相关核心接口的作用,本文来介绍下BeanPostProcessor接口
BeanPostProcessor
该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。接口的源码如下
public interface BeanPostProcessor {Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;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容器中*/@Overridepublic 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容器中*/@Overridepublic 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方法是在自定义初始化方法执行之后执行的。
注意!!!
- BeanFactory和ApplicationContext两个容器对待bean的后置处理器稍微有些不同。ApplicationContext容器会自动检测Spring配置文件中那些bean所对应的Java类实现了BeanPostProcessor接口,并自动把它们注册为后置处理器。在创建bean过程中调用它们,所以部署一个后置处理器跟普通的bean没有什么太大区别。
- BeanFactory容器注册bean后置处理器时必须通过代码显示的注册,在IoC容器继承体系中的ConfigurableBeanFactory接口中定义了注册方法
/*** Add a new BeanPostProcessor that will get applied to beans created* by this factory. To be invoked during factory configuration.* <p>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容器中*/@Overridepublic 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容器中*/@Overridepublic 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容器中*/@Overridepublic 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容器中*/@Overridepublic 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容器中*/@Overridepublic 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容器中*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("A after...实例化的bean对象:"+bean+"\t"+beanName);// 可以根据beanName不同执行不同的处理操作return bean;}@Overridepublic int getOrder() {// TODO Auto-generated method stubreturn 10;}
}
public class MyBeanPostProcessor2 implements BeanPostProcessor,Ordered{/*** 实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务* 注意:方法返回值不能为null* 如果返回null那么在后续初始化方法将报空指针异常或者通过getBean()方法获取不到bena实例对象* 因为后置处理器从Spring IoC容器中取出bean实例对象没有再次放回IoC容器中*/@Overridepublic 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容器中*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("B after...实例化的bean对象:"+bean+"\t"+beanName);// 可以根据beanName不同执行不同的处理操作return bean;}@Overridepublic int getOrder() {// TODO Auto-generated method stubreturn 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接口的作用应该比较清楚了。
欢迎大家私信博主,邀你进技术交流群