spring的BeanPostProcessor分析

1:作用

在spring bean的生命周期中加入自定义逻辑。

2:接口

源码:

public interface BeanPostProcessor {
	// 该方法在调用完毕构造方法,setter方法后,执行init-method方法前
	// 执行,参数为当前状态下的bean,以及bean的名称
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	// 该方法在init-method方法调用完毕后执行
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

2:例子

在BeanFactory中不会自动注册自定义的BeanPostProcessor,需要通过API添加,但是在ApplicationContext体系中会自动检测并添加调用。

2.1:定义Bean

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 中自定义的初始化方法");
	}
}

2.2:定义自定义后置bean处理器

public class MyBeanPostProcessor implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("before--实例化的bean对象:"+bean+"\t"+beanName);
		// 可以根据beanName不同执行不同的处理操作
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("after...实例化的bean对象:"+bean+"\t"+beanName);
		// 可以根据beanName不同执行不同的处理操作
		return bean;
	}
}

2.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="yudaosourcecode.postprocessor.User" id="user" init-method="start">
        <property name="name" value="波波烤鸭" />
    </bean>

    <!-- 注册处理器 -->
    <bean class="yudaosourcecode.postprocessor.MyBeanPostProcessor"/>
</beans>

2.4:BeanFactory测试

@Test
public void testBeanDefinitionWithBeanFacotry() {
    XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("testbeandefinition.xml"));
    xbf.getBean("user");
}

运行:

User 被实例化
设置:波波烤鸭
User 中自定义的初始化方法

此时可以看到自定义的后置bean处理器并没有生效,修改代码,手动添加后置bean处理器:

@Test
public void testBeanDefinitionWithBeanFacotry() {
    XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("testbeandefinition.xml"));
    xbf.addBeanPostProcessor(new MyBeanPostProcessor());
    xbf.getBean("user");
}

运行:

User 被实例化
设置:波波烤鸭
before--实例化的bean对象:yudaosourcecode.postprocessor.User@610694f1	user
User 中自定义的初始化方法
after...实例化的bean对象:yudaosourcecode.postprocessor.User@610694f1	user

可以看到此时后置bean处理器就生效了。
我们就着BeanFactory来看下多个后置处理器的情况,再定义一个:

public class MyBeanPostProcessor1 implements BeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("111before--实例化的bean对象:"+bean+"\t"+beanName);
		// 可以根据beanName不同执行不同的处理操作
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		System.out.println("111after...实例化的bean对象:"+bean+"\t"+beanName);
		// 可以根据beanName不同执行不同的处理操作
		return bean;
	}
}

修改测试代码:

@Test
public void testBeanDefinitionWithBeanFacotry() {
    XmlBeanFactory xbf = new XmlBeanFactory(new ClassPathResource("testbeandefinition.xml"));
    xbf.addBeanPostProcessor(new MyBeanPostProcessor());
    xbf.addBeanPostProcessor(new MyBeanPostProcessor1());
    xbf.getBean("user");
}

运行:

User 被实例化
设置:波波烤鸭
before--实例化的bean对象:yudaosourcecode.postprocessor.User@610694f1	user
111before--实例化的bean对象:yudaosourcecode.postprocessor.User@610694f1	user
User 中自定义的初始化方法
after...实例化的bean对象:yudaosourcecode.postprocessor.User@610694f1	user
111after...实例化的bean对象:yudaosourcecode.postprocessor.User@610694f1	user

可以看到调用过程使用的是典型的责任链方式完成的,before先执行的后执行after。

2.5:ApplicationContext测试

@Test
public void testBeanDefinitionWithApplicationContext() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("testbeandefinition.xml");
    ac.getBean(User.class);
}

运行:

User 被实例化
设置:波波烤鸭
before--实例化的bean对象:yudaosourcecode.postprocessor.User@28ac3dc3	user
User 中自定义的初始化方法
after...实例化的bean对象:yudaosourcecode.postprocessor.User@28ac3dc3	user
上一篇:P1200


下一篇:spring 注解学习 二spring bean的生命周期