0x01 描述
Bean后置处理器允许在Bean的创建过程中做出相应的调整(回调相应的后置处理器)从而使Bean成为符合我们需求的Bean注:ApplicationContext会自动检测由BeanPostProcessor接口的实现定义的Bean注册这些Bean为后置处理器,然后通过在容器中创建Bean,在适当的时候调用它
0x02 Bean加载过程图
可以大致看一下,这样可以更好的理解后置处理器注: 有错的话,可以联系我进行修改
Spring Bean加载过程.xmind
0x03 Bean后置处理器
0x03.1 BeanPostProcessor
BeanPostProcessor:就是帮助我们在bean实例化之后,初始化前后做一些事情
类继承BeanPostProcessor以后会出现如下方法可供使用:postProcessBeforeInitialization:初始化之前执行,该方法的返回值类型是ObjectpostProcessAfterInitialization:初始化完毕时执行,该方法的返回值类型是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.javapackage 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.javaimport 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.javapackage 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.javapackage 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.javapackage 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.javapackage 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.javapackage 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.javapackage 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.javapackage com.test.循环依赖;public class ServiceA { private ServiceB serviceB; public void setServiceB(ServiceB serviceB) { this.serviceB = serviceB; } public ServiceB getServiceB() { return serviceB; }}// 文件名: ServiceB.javapackage 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.javaimport 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: serviceATestpredictBeanType: serviceBTestpredictBeanType: serviceATestpredictBeanType: serviceBTestdetermineCandidateConstructors: serviceATestdetermineCandidateConstructors: serviceBTestgetEarlyBeanReference: serviceATest