0x01 描述
Bean后置处理器允许在Bean的创建过程中做出相应的调整(回调相应的后置处理器)
从而使Bean成为符合我们需求的Bean
注:
ApplicationContext会自动检测由BeanPostProcessor接口的实现定义的Bean
注册这些Bean为后置处理器,然后通过在容器中创建Bean,在适当的时候调用它
0x02 Bean加载过程图
可以大致看一下,这样可以更好的理解后置处理器
注: 有错的话,可以联系我进行修改
Spring Bean加载过程.xmind
0x03 Bean后置处理器
0x03.1 BeanPostProcessor
BeanPostProcessor:
就是帮助我们在bean实例化之后,初始化前后做一些事情
类继承BeanPostProcessor以后会出现如下方法可供使用:
postProcessBeforeInitialization:
初始化之前执行,该方法的返回值类型是Object
postProcessAfterInitialization:
初始化完毕时执行,该方法的返回值类型是Object
0x03.2 InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口
在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置
类继承InstantiationAwareBeanPostProcessor以后会出现如下方法可供使用:
postProcessBeforeInstantiation():
在目标对象实例化之前调用,该方法的返回值类型是Object
由于这个时候目标对象还未被实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例
注: 如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessorAfterIniaialization方法会调用,其他方法不再调用
postProcessAfterInstantiation():
在目标对象实例化之后调用,该方法的返回值类型是boolean
这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null
注一: 不管postProcessBeforeInstantiation()返回什么都会执行
注二: 如果该方法的返回值是false,会忽略postProcessProperties()与postProcessPropertyValues()方法的执行
postProcessProperties():
对属性值进行修改,该方法的返回值类型是PropertyValues
这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值
注: 如果postProcessAfterInstantiation()返回false, 该方法不会被调用
postProcessPropertyValues():
对属性值进行修改,该方法的返回值类型是PropertyValues
这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值
对比postProcessProperties()方法多了个PropertyDescriptor[]参数
注: 如果postProcessAfterInstantiation()返回false, 该方法不会被调用
注二: 如果执行了postProcessProperties(),那么本方法就不会被执行
0x03.3 MergedBeanDefinitionPostProcessor
MergedBeanDefinitionPostProcessor接口继承BeanPostProcessor接口
它是一个用于合并BeanDefinition的后置处理器
一般我们作为Spring的用户来说不会用到它,除非有些特殊的需要
类继承MergedBeanDefinitionPostProcessor以后会出现如下方法可供使用:
postProcessMergedBeanDefinition():
缓存bean注入信息的后置处理器,该方法无返回值
仅仅是缓存或者说是查询,没有完成注入
0x03.4 DestructionAwareBeanPostProcessor
DestructionAwareBeanPostProcessor接口继承BeanPostProcessor接口
销毁Bean后置处理器
类继承DestructionAwareBeanPostProcessor以后会出现如下方法可供使用:
requiresDestruction:
检测bean是否需要注册销毁方法,该方法的返回值类型是boolean
注: 如果该方法的返回值是false,会忽略postProcessBeforeDestruction()方法的执行
postProcessBeforeDestruction:
Bean销毁之前的行为处理回调方法,该回调只能应用到单例Bean,该方法无返回值
注: 如果requiresDestruction()返回false, 该方法不会被调用
0x03.5 SmartInitializingSingleton
SmartInitializingSingleton接口是一个独立的接口
主要用于在IOC容器基本启动完成时进行扩展
SmartInitializingSingleton是所有的非延迟的、单例的bean都初始化后调用,只调用一次
如果是多例的bean实现,不会调用
类继承SmartInitializingSingleton以后会出现如下方法可供使用:
afterSingletonsInstantiated():
当所有单例bean都初始化完成以后,容器会回调该接口的方法
主要应用场合就是在所有单例bean创建完成之后,可以在该回调中做一些事情
0x03.6 SmartInstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor接口继承InstantiationAwareBeanPostProcessor接口
智能实例化Bean后置处理器
类继承SmartInstantiationAwareBeanPostProcessor以后会出现如下方法可供使用:
predictBeanType():
预测bean的类型,该方法的返回值类型是Class<?>
determineCandidateConstructors():
监测Bean的构造器,该方法的返回值类型是Constructor<?>[]
getEarlyBeanReference():
循环引用的后置处理器,该方法的返回值类型是Object
这个比较复杂,获取提前暴露的bean引用
主要用于解决循环引用的问题,并且只有单例对象才会调用此方法(一般是bean自身,如果是代理对象则需要取用代理引用)
0x04 前置操作
// 在./SpringDemo/src/main/java/com/test/创建个HelloWorld.java
// 目录: ./SpringDemo/src/main/java/com/test/
// 文件名: HelloWorld3.java
package com.test;
public class HelloWorld3 {
private String message;
public void setMessage(String message) {
this.message = message;
}
public void getMessage() {
System.out.println("Your Message: " + message);
}
public void init() {
System.out.println("这个bean进行了初始化");
}
public void destroy() {
System.out.println("这个bean被销毁了");
}
}
// 在./SpringDemo/src/main/resources/创建个applicationContext2.xml
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext2.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
// 在<beans>标签中,中配置HelloWorld3的信息, 设定message的值为“Hello World!”
// 这里提供一个配置好的applicationContext2.xml文件
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext2.xml
<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.xsd">
<bean id="helloWorldTest3" class="com.test.HelloWorld3" init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
// 创建一个测试类Test9进行测试
// 目录: ./SpringDemo/src/test/java/
// 文件名: Test9.java
import com.test.HelloWorld3;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test9 {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
HelloWorld3 obj = (HelloWorld3) context.getBean("helloWorldTest3");
obj.getMessage();
// 注册一个关闭钩子,关闭Spring IOC容器
// 用来触发bean标签的destroy-method属性
context.registerShutdownHook();
}
}
0x05 小例子
0x05.1 BeanPostProcessor
// 第一步
// 创建个BeanPostProcessor后置处理器,进行测试
// 目录: ./SpringDemo/src/main/java/com/test/Bean后置处理器/
// 文件名: BeanPostProcessorTest.java
package com.test.Bean后置处理器;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class BeanPostProcessorTest implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeforeInitialization: " + beanName + " " + "正在执行预初始化方法");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("AfterInitialization: " + beanName + " " + "正在执行后初始化方法");
return bean;
}
}
// 第二步
// 修改applicationContext2.xml引入BeanPostProcessor后置处理器
// 这里提供一个配置好的applicationContext2.xml文件
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext2.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.test.Bean后置处理器.BeanPostProcessorTest"/>
<bean id="helloWorldTest3" class="com.test.HelloWorld3" init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
// 第三步
// 目录: ./SpringDemo/src/test/java/
// 文件名: Test9.java
// 运行Test9.java
// 运行结果
BeforeInitialization: helloWorldTest3 正在执行预初始化方法
这个bean进行了初始化
AfterInitialization: helloWorldTest3 正在执行后初始化方法
Your Message: Hello World!
这个bean被销毁了
0x05.2 InstantiationAwareBeanPostProcessor
// 第一步
// 创建个InstantiationAwareBeanPostProcessor后置处理器,进行测试
// 目录: ./SpringDemo/src/main/java/com/test/Bean后置处理器/
// 文件名: InstantiationAwareBeanPostProcessorTest.java
package com.test.Bean后置处理器;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.TypedStringValue;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import java.beans.PropertyDescriptor;
public class InstantiationAwareBeanPostProcessorTest implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("postProcessBeforeInstantiation: " + beanName + " ");
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
// 注: 如果该方法的返回值是false,会忽略postProcessProperties与postProcessPropertyValues()方法的执行
System.out.println("postProcessAfterInstantiation: " + beanName + " ");
return true;
}
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if (beanName.equals("helloWorldTest3")) {
// 获取bean名为helloWorldTest3的message属性数据
PropertyValue pv = pvs.getPropertyValue("message");
TypedStringValue obj = (TypedStringValue) pv.getValue();
// 修改message属性数据
// 固定在message属性值的最后面添加一句: 属性值修改测试
MutablePropertyValues p = new MutablePropertyValues();
p.add("message", obj.getValue() + " " + "属性值修改测试-postProcessProperties");
return p;
} else {
return pvs;
}
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("postProcessPropertyValues: " + beanName + " ");
if (beanName.equals("helloWorldTest3")) {
// 获取bean名为helloWorldTest3的message属性数据
PropertyValue pv = pvs.getPropertyValue("message");
TypedStringValue obj = (TypedStringValue) pv.getValue();
// 修改message属性数据
// 固定在message属性值的最后面添加一句: 属性值修改测试
MutablePropertyValues p = new MutablePropertyValues();
p.add("message", obj.getValue() + " " + "属性值修改测试-postProcessPropertyValues");
return p;
} else {
return pvs;
}
}
}
// 第二步
// 修改applicationContext2.xml引入InstantiationAwareBeanPostProcessor后置处理器
// 这里提供一个配置好的applicationContext2.xml文件
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext2.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.test.Bean后置处理器.InstantiationAwareBeanPostProcessorTest"/>
<bean id="helloWorldTest3" class="com.test.HelloWorld3" init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
// 第三步
// 目录: ./SpringDemo/src/test/java/
// 文件名: Test9.java
// 运行Test9.java
// 使用了postProcessProperties()方法的运行结果
postProcessBeforeInstantiation: helloWorldTest3
postProcessAfterInstantiation: helloWorldTest3
postProcessProperties: helloWorldTest3
这个bean进行了初始化
Your Message: Hello World! 属性值修改测试-postProcessProperties
这个bean被销毁了
// 注释了postProcessProperties()方法的运行结果
postProcessBeforeInstantiation: helloWorldTest3
postProcessAfterInstantiation: helloWorldTest3
postProcessPropertyValues: helloWorldTest3
这个bean进行了初始化
Your Message: Hello World! 属性值修改测试-postProcessPropertyValues
这个bean被销毁了
0x05.3 MergedBeanDefinitionPostProcessor
// 第一步
// 创建个MergedBeanDefinitionPostProcessor后置处理器,进行测试
// 目录: ./SpringDemo/src/main/java/com/test/Bean后置处理器/
// 文件名: MergedBeanDefinitionPostProcessorTest.java
package com.test.Bean后置处理器;
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
public class MergedBeanDefinitionPostProcessorTest implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition rootBeanDefinition, Class<?> aClass, String s) {
System.out.println("postProcessMergedBeanDefinition: " + s);
}
}
// 第二步
// 修改applicationContext2.xml引入MergedBeanDefinitionPostProcessor后置处理器
// 这里提供一个配置好的applicationContext2.xml文件
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext2.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.test.Bean后置处理器.MergedBeanDefinitionPostProcessorTest"/>
<bean id="helloWorldTest3" class="com.test.HelloWorld3" init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
// 第三步
// 目录: ./SpringDemo/src/test/java/
// 文件名: Test9.java
// 运行Test9.java
// 运行结果
postProcessMergedBeanDefinition: helloWorldTest3
这个bean进行了初始化
Your Message: Hello World!
这个bean被销毁了
0x05.4 DestructionAwareBeanPostProcessor
// 第一步
// 创建个DestructionAwareBeanPostProcessor后置处理器,进行测试
// 目录: ./SpringDemo/src/main/java/com/test/Bean后置处理器/
// 文件名: DestructionAwareBeanPostProcessorTest.java
package com.test.Bean后置处理器;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
public class DestructionAwareBeanPostProcessorTest implements DestructionAwareBeanPostProcessor {
@Override
public boolean requiresDestruction(Object bean) {
// 注: 如果该方法的返回值是false,会忽略postProcessBeforeDestruction()方法的执行
System.out.println("requiresDestruction: " + bean.getClass().getSimpleName() + " ");
return DestructionAwareBeanPostProcessor.super.requiresDestruction(bean);
}
@Override
public void postProcessBeforeDestruction(Object o, String s) throws BeansException {
System.out.println("postProcessBeforeDestruction: " + s + " ");
}
}
// 第二步
// 修改applicationContext2.xml引入DestructionAwareBeanPostProcessor后置处理器
// 这里提供一个配置好的applicationContext2.xml文件
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext2.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.test.Bean后置处理器.DestructionAwareBeanPostProcessorTest"/>
<bean id="helloWorldTest3" class="com.test.HelloWorld3" init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
// 第三步
// 目录: ./SpringDemo/src/test/java/
// 文件名: Test9.java
// 运行Test9.java
// 运行结果
这个bean进行了初始化
requiresDestruction: HelloWorld3
Your Message: Hello World!
postProcessBeforeDestruction: helloWorldTest3
这个bean被销毁了
0x05.5 SmartInitializingSingleton
// 第一步
// 创建个SmartInitializingSingleton后置处理器,进行测试
// 目录: ./SpringDemo/src/main/java/com/test/Bean后置处理器/
// 文件名: SmartInitializingSingletonTest.java
package com.test.Bean后置处理器;
import org.springframework.beans.factory.SmartInitializingSingleton;
public class SmartInitializingSingletonTest implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("SmartInitializingSingleton后置处理器的afterSingletonsInstantiated()方法被执行了");
}
}
// 第二步
// 修改applicationContext2.xml引入SmartInitializingSingleton后置处理器
// 这里提供一个配置好的applicationContext2.xml文件
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext2.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.test.Bean后置处理器.SmartInitializingSingletonTest"/>
<bean id="helloWorldTest3" class="com.test.HelloWorld3" init-method="init" destroy-method="destroy">
<property name="message" value="Hello World!"/>
</bean>
</beans>
// 第三步
// 目录: ./SpringDemo/src/test/java/
// 文件名: Test9.java
// 运行Test9.java
// 运行结果
这个bean进行了初始化
SmartInitializingSingleton后置处理器的afterSingletonsInstantiated()方法被执行了
Your Message: Hello World!
这个bean被销毁了
0x05.6 SmartInstantiationAwareBeanPostProcessor
getEarlyBeanReference()方法的触发,比较复杂,获取提前暴露的bean引用
主要用于解决循环引用的问题,并且只有单例对象才会调用此方法
因此这里整一个拥有循环引用问题的代码
来触发SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference()方法
// 第一步
// 创建个SmartInstantiationAwareBeanPostProcessor后置处理器,进行测试
// 目录: ./SpringDemo/src/main/java/com/test/Bean后置处理器/
// 文件名: SmartInstantiationAwareBeanPostProcessorTest.java
package com.test.Bean后置处理器;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import java.lang.reflect.Constructor;
public class SmartInstantiationAwareBeanPostProcessorTest implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("predictBeanType: " + beanName);
return beanClass;
}
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("determineCandidateConstructors: " + beanName);
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
System.out.println("getEarlyBeanReference: " + beanName);
return bean;
}
}
// 第二步
// 创建个拥有循环依赖的代码,进行测试
// 目录: ./SpringDemo/src/main/java/com/test/循环依赖/
// 文件名: ServiceA.java
package com.test.循环依赖;
public class ServiceA {
private ServiceB serviceB;
public void setServiceB(ServiceB serviceB) {
this.serviceB = serviceB;
}
public ServiceB getServiceB() {
return serviceB;
}
}
// 文件名: ServiceB.java
package com.test.循环依赖;
public class ServiceB {
private ServiceA serviceA;
public void setServiceA(ServiceA serviceA) {
this.serviceA = serviceA;
}
public ServiceA getServiceA() {
return serviceA;
}
}
// 第三步
// 创建个applicationContext3.xml引入SmartInstantiationAwareBeanPostProcessor后置处理器
// 这里提供一个配置好的applicationContext3.xml文件
// 目录: ./SpringDemo/src/main/resources/
// 文件名: applicationContext3.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="com.test.Bean后置处理器.SmartInstantiationAwareBeanPostProcessorTest"/>
<bean id="serviceATest" class="com.test.循环依赖.ServiceA">
<property name="serviceB" ref="serviceBTest"/>
</bean>
<bean id="serviceBTest" class="com.test.循环依赖.ServiceB">
<property name="serviceA" ref="serviceATest"/>
</bean>
</beans>
// 第四步
// 创建一个测试类Test10进行测试
// 目录: ./SpringDemo/src/test/java/
// 文件名: Test10.java
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test10 {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");
context.getBean("serviceATest");
}
}
// 运行结果
predictBeanType: serviceATest
predictBeanType: serviceBTest
predictBeanType: serviceATest
predictBeanType: serviceBTest
determineCandidateConstructors: serviceATest
determineCandidateConstructors: serviceBTest
getEarlyBeanReference: serviceATest