上一篇我们知道了 Spring 中 bean 工厂后置处理器 的作用和触发时间。
作用:允许我们在工厂里所有的 bean 被加载进来后但是还没初始化前,对所有 bean 的属性进行修改也可以 add 属性值。
触发时间:先执行工厂后置处理器,再执行构造方法,最后 init-method。
本篇我们学习 BeanPostProcessor, 和 BeanFactoryPostProcessor 仅差一个 Factory,可以推断后者是针对工厂,前者是针对 bean 元素。
我们来看一下 BeanPostProcessor 的两个方法
注意:
- package org.springframework.beans.factory.config;
- import org.springframework.beans.BeansException;
- public interface BeanPostProcessor {
- //实例化、依赖注入完毕,在调用显示的初始化之前完成一些定制的初始化任务
- Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
- //实例化、依赖注入、初始化完毕时执行
- Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
- }
BeanFactory 和 ApplicationContext 两个容器对待 bean 的后置处理器稍微有些不同。ApplicationContext 容器会自动检测 Spring 配置文件中那些 bean 所对应的 Java 类实现了 BeanPostProcessor
接口,并自动把它们注册为后置处理器。在创建 bean 过程中调用它们,所以部署一个后置处理器跟普通的 bean 没有什么太大区别。
接下来我们通过案例来分析它的用法:
beans.xml
- <?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-2.5.xsd">
- <bean id="user" init-method="init" class="xz.quartz.analysis.User"></bean>
- <!-- Bean后置处理器 -->
- <bean id="beanpostpro" class="xz.quartz.analysis.beanpostpro"></bean>
- </beans>
这里我们注册了一个普通类 User 和一个 BeanPostProcessor 类
User 类
user 类里包含了 init-method 和 construtor
- package xz.quartz.analysis;
- public class User {
- String name;
- String age;
- void init() {
- System.out.println("init");
- name = "zx-init";
- age = "zx-init";
- System.out.println("name:" + name + ",age:" + age);
- }
- public User() {
- System.out.println("construtor");
- name = "zx-construtor";
- age = "zx-construtor";
- System.out.println("name:" + name + ",age:" + age);
- }
- public void go() {
- System.out.println("最终age的值:" + age);
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getAge() {
- return age;
- }
- public void setAge(String age) {
- this.age = age;
- }
- }
BeanPostProcessor 实现类
- package xz.quartz.analysis;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanPostProcessor;
- public class beanpostpro implements BeanPostProcessor{
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("before"+beanName);
- return bean;
- }
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("after"+beanName);
- return bean;
- }
- }
main 函数
- public class xz {
- public static void main(String[] args) {
- ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:beans.xml");
- System.out.println("获取到User实例 ");
- ((User)applicationContext.getBean("user")).go();
- }
- }
运行结果
- construtor
- name:zx-construtor,age:zx-construtor
- beforeuser
- init
- name:zx-init,age:zx-init
- afteruser
- 获取到User实例
- 最终age的值:zx-init
通过这个例子我们可以得出结论
执行顺序:构造方法—>BeanPostProcessor 的 before—>init-method—>BeanPostProcessor 的 after。
我们把上篇提到的 BeanFactoryPostProcessor 也加进来看一下效果
- package xz.quartz.analysis;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.MutablePropertyValues;
- import org.springframework.beans.factory.config.BeanDefinition;
- import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
- import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
- public class beanfactorypostpro implements BeanFactoryPostProcessor{
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- System.out.println("******调用BeanFactoryPostProcessor开始");
- String[] beanStr = beanFactory.getBeanDefinitionNames();
- for (String beanName : beanStr) {
- System.out.println("bean name:"+beanName);
- if ("user".equals(beanName)) {
- BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
- System.out.println("修改user的age值");
- beanDefinition.getPropertyValues().add("age", "20");
- }
- }
- System.out.println("******调用BeanFactoryPostProcessor结束");
- }
- }
运行结果
- ******调用BeanFactoryPostProcessor开始
- bean name:user
- 修改user的age值
- bean name:beanfactorypostpro
- bean name:beanpostpro
- ******调用BeanFactoryPostProcessor结束
- construtor
- name:zx-construtor,age:zx-construtor
- beforeuser
- init
- name:zx-init,age:zx-init
- afteruser
- 获取到User实例
- 最终age的值:zx-init
到这里我们可以得出结论
1. 执行顺序:BeanFactoryPostProcessor—> 构造方法—>BeanPostProcessor 的 before—>init-method—>BeanPostProcessor 的 after.
2. 实际运用中,可以配置多个 BeanFactoryPostProcessor 和 BeanPostProcessor
3. 应用场景1. 解析 bean 的注解,将注解中的字段转化为属性
2、统一将属性在执行前,注入 bean 中,如数据库访问的 sqlMap,如严重服务,这样不需要每个 bean 都配置属性
3、打印日志,记录时间等。
来源: http://www.jianshu.com/p/f80b77d65d39