文章目录
BeanPostProcessor简介
BeanPostProcessor
是一个容器的扩展点,它可以在 bean
的生命周期过程中,初始化阶段前后添加自定义处理逻辑,并且不同 IOC
容器间的 BeanPostProcessor
不会相互干预。
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor执行时机
Bean的几种额外的初始化方法: @PostConstruct
、InitializingBean接口
、init-method
。
初始化执行顺序:
- 构造方法
- @PostConstruct
- InitializingBean 的 afterPropertiesSet 方法
- init-method
bean 的生命周期:
加入BeanPostProcessor
后置处理器的执行流程:
Bean 的初始化阶段的全流程: BeanPostProcessor#postProcessBeforeInitialization
→ @PostConstruct
→ InitializingBean
→ init-method
→ BeanPostProcessor#postProcessAfterInitialization
BeanPostProcessor的使用
声明bean:
public class Dog implements InitializingBean {
public void initMethod() {
System.out.println("initMethod ...");
}
@PostConstruct
public void postConstruct() {
System.out.println("PostConstruct ...");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean ...");
}
}
编写后置处理器:
public class ExecuteTimeBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Dog) {
System.out.println("postProcessBeforeInitialization ...");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof Dog) {
System.out.println("postProcessAfterInitialization ...");
}
return bean;
}
}
编写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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dog" class="com.example.Dog" init-method="initMethod"/>
<bean class="com.example.ExecuteTimeBeanPostProcessor"/>
<!-- 记得开注解配置,否则@PostConstruct不生效 -->
<context:annotation-config/>
</beans>
测试运行:
public class BeanPostProcessorExecuteTimeApplication {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"executetime.xml");
ctx.close();
}
}
启动容器,容器中所有的Bean都会被上面的后置处理器进行初始化前后处理。
postProcessBeforeInitialization ...
PostConstruct ...
InitializingBean ...
initMethod ...
postProcessAfterInitialization ...
BeanPostProcessor源码解析
* 遍历得到容器中所有的BeanPostProcessor;挨个执行postProcessBeforeInitialization,
* 一但返回null,跳出for循环,不会执行后面的BeanPostProcessor.postProcessorsBeforeInitialization
*
* BeanPostProcessor原理
* populateBean(beanName, mbd, instanceWrapper);给bean进行属性赋值
* initializeBean
* {
* applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
* invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
* applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
*}
打断点
Debug运行单元测试,查看执行堆栈。
DefaultListableBeanFactory.java
点到preInstantiateSingletons
方法,方法内容是循环BeanNames来创建Bean组件。
AbstractAutowireCapableBeanFactory.java
点到initializeBean
方法,方法内容是初始化一个Bean。
发现在执行自定义初始化方法的前后会执行后置处理器中的方法。
下面是获取所有后置处理器后,循环执行后置处理器中方法的具体代码块。
以上就是BeanPostProcessor源码解析的关键代码。
BeanPostProcessor在Spring底层的使用
Spring容器中Bean赋值,注入其他组件,@Autowired,生命周期注解功能,@Async等,都是用BeanPostProcessor后置处理器来实现的。
查看下BeanPostProcessor的所有实现类。
分析为什么实现ApplicationContextAware
接口就能注入ApplicationContext
上下文。
其实就是用ApplicationContextAwareProcessor
这个后置处理器实现类来实现的。
查看ApplicationContextAwareProcessor源码:
实现了BeanPostProcessor。
我们已经知道Spring容器在初始化之前会调用后置处理器中的postProcessBeforeInitialization方法,所以上面的代码会在初始化一个Bean的时候被执行,关键看标出来的这行代码,就知道为什么实现了ApplicationContextAware
接口就能注入ApplicationContext
上下文的。
InstantiationAwareBeanPostProcessor
执行时机: