BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方法。BeanPostProcessor的源码如下:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
一共包含两个方法 postProcessBeforeInitialization 和 postProcessAfterInitialization ,从名称就可以看出来分别对应是bean初始化前的处理和bean初始化后的处理,方法中的参数也是一样,参数Object bean代表容器中所有的bean。
另外,Spring还提供了类似的处理,在bean创建时还提供了xml配置自定义的init-method 和destory-method方法,也可以做到类似的功能,不过destory-method是在bean销毁时候触发调用。
与destory-method功能类似的,Spring还提供了了一个DisposableBean接口,通过实现该接口,复写destroy方法,可以在bean销毁时做一些额外提供的事。
public interface DisposableBean {
void destroy() throws Exception;
}
下面通过代码来验证一下:
新建一个Student 类,提供构造函数,其中myInit和myDestory是为了对比在xml配置中提供默认的初始化配置方法
public class Student {
private String name;
public Student(String name) {
System.out.println("初始化student:"+name);
this.name = name;
}
@Override
public String toString() {
return "Student [name=" + name + "]";
}
public void myInit() {
System.out.println("默认init方法...");
}
public void myDestory() {
System.out.println("默认destory方法...");
}
//省略get/set...
}
Person类,包含属性Student类,其中initMethod和destoryMethod是为了对比配置文件中指定init-methid和destory-method提供的方法
public class Person implements DisposableBean {
private String name = "wuxiaojun";
private int age;
private Student student;
public void echo() {
System.out.println("I'm a student : " + student);
}
public void initMethod() {
System.out.println("初始化bean...initMethod");
}
public void destoryMethod() {
System.out.println("销毁bean...destoryMethod");
}
@Override
public void destroy() throws Exception {
System.out.println("执行销毁方法destroy");
}
//省略get/set...
}
spring配置文件
<?xml version="1.0" encoding="ISO-8859-1"?>
<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
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd"
default-init-method="myInit" default-destroy-method="myDestory">
<bean id="person" class="wmj.Person" init-method="initMethod" destroy-method="destoryMethod">
<property name="student" ref="student" />
</bean>
<bean class="wmj.Student" id="student">
<constructor-arg index="0" value="test" />
</bean>
<bean class="wmj.MyBeanPostProcessor" />
</beans>
测试类
@Test
public void testApplicationLoad() {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"wmjbeans/beanFactoryTest.xml");
Person person = (Person) ctx.getBean("person");
assertEquals("wuxiaojun", person.getName());
System.out.println("ClassPathXmlApplicationContext===>"+person.getName());
((AbstractApplicationContext) ctx).close();
}
执行上面代码,结果如下:
可以看到,因为person依赖于student,所以容器启动先加载student,
而因为配置中提供了默认的初始化方法default-init-method和默认销毁方法default-destroy-method入口,所以在初始化student时,会进入执行myInit。
接下来初始化person,在初始化之前执行postProcessBeforeInitialization,然后执行xml中的initMethod,初始化结束后执行后处理器postProcessAfterInitialization,最后销毁bean。
从上可以得看出 ,同时配置init-method 和BeanPostProcessor,Spring会先处理前处理器的活动,再处理配置的活动,初始化完成也是先处理后处理器的活动。
在bean销毁时,也是有限处理接口DisposableBean的销毁方法,后处理destory-method的活动。
在这里大致说一下Spring的实例化过程:
实例化Bean对象 → 设置对象属性 → 检查Aware相关接口并设置相关依赖→ BeanPostProcessor前置处理 → 检查是否是InitializingBean以决定是否调用afterPropertiesSet方法 → 检查是否配置有自定义的init-method方法→ BeanPostProcessor后置处理 → 是否实现DisposableBean接口 → 是否配置有自定义的destroy方法