最近在查看Spring Boot启动源码,学习重要的 AbstractApplicationContext
中refresh()
方法,发现其中有个关于 bean 创建时拦截的知识点。
一、接口定义
先查看 BeanPostProcessor
接口定义。
// 允许自定义修改一个bean 的实例化的工厂钩子
// 注册:ApplicationContext 获取 BeanPostProcessor 的 bean,并且应用于之后的所有 bean 的创建
// 排序:BeanPostProcessor 根据实现的 Ordered 或 PriorityOrdered 或都不实现进行排序
public interface BeanPostProcessor {
// 在 bean 实例化调用任何初始化回掉之前执行。如 InitializingBean#afterPropertiesSet 或者 @PostConstruct
// 参数:bean bean实例 beanName bean 名称
// 返回:使用的bean 实例。如果为null,就不执行后续的 BeanPostProcessors 处理
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// 在 bean 实例化调用任何初始化回掉之后执行。
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
二、源码实现
再查看具体源码实现AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException {
/*...*/
// Register bean processors that intercept bean creation.
// 注册 bean 处理器来拦截 bean 的创建
registerBeanPostProcessors(beanFactory);
/*...*/
}
查看方法
方法注释:实例化并且注册所有的
BeanPostProcessor
bean,并且如果有给定顺序,要按照给定顺序执行。
必须在任何application
bean 实例化之前调用。
这里有一点,application
对应 bean 的 role,分为 BeanDefinition#ROLE_APPLICATION
、BeanDefinition#ROLE_INFRASTRUCTURE
、BeanDefinition#ROLE_SUPPORT
。
再接着跟进查看方法
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 获取容器中的所有实现 BeanPostProcessor 的bean的名字
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 手动添加一个 BeanPostProcesser 的bean实例到处理链中
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 这里根据实现 BeanPostProcessors 的实现类是否同时实现了 PriorityOrdered 接口,
// Ordered 接口 或者都没有实现 来进行区分
// 实现了 PriorityOrdered 接口的
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
// 实现了 Ordered 接口的
List<String> orderedPostProcessorNames = new ArrayList<>();
// 两个接口都没有实现的
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 遍历所有的 BeanPostProcessor 的bean,然后根据 排序 添加到不同的集合里面
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// 这里根据实现了 PriorityOrdered 接口的 BeanPostProcesser 实例进行排序后,
// 优先添加到 BeanPostProcesser 的处理链中
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// 然后排序处理实现了 Ordered 接口的 BeanPostProcesser 实例 添加到处理链中
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
//最后再处理其它的
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 最后在处理链末尾手动添加一个 处理器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
到这里说明了 BeanPostProcessor
的添加顺序。
三、测试执行顺序
测试一
// 新建一个bean 实现了 InitializingBean 接口,并且有一个 @PostConstruct 标注的初始化方法。打印所执行的方法。
@Component
public class InitializingBeanImplTest implements InitializingBean {
// 构造函数
public InitializingBeanImplTest() {
System.out.println(InitializingBeanImplTest.class.getName() + "#Constructor");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println(InitializingBeanImplTest.class.getName() + " :: " + InitializingBean.class.getName() + "#afterPropertiesSet");
}
@PostConstruct
public void init() {
System.out.println(InitializingBeanImplTest.class.getName() + " :: " + PostConstruct.class.getName());
}
}
// 新建一个 bean 实现 BeanPostProcessorImplTest 接口,重写两个方法。打印类名和执行方法名称
@Component
public class BeanPostProcessorImplTest implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(BeanPostProcessorImplTest.class.getSimpleName() + " :: " + bean.getClass().getName() + "#postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(BeanPostProcessorImplTest.class.getSimpleName() + " :: " + bean.getClass().getName() + "#postProcessAfterInitialization");
return bean;
}
}
执行结果
有两个点:
1、 BeanPostProcessorImplTest
利用编辑器查找匹配 604 次
2、执行顺序:构造函数 -> postProcessBeforeInitialization
-> @PostConstruct
-> InitializingBean#afterPropertiesSet
-> postProcessAfterInitialization
测试二
修改 BeanPostProcessorImplTest
,实现 Ordered
接口,并且设置最高优先权
@Component
public class BeanPostProcessorImplTest implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(BeanPostProcessorImplTest.class.getSimpleName() + " :: " + bean.getClass().getName() + "#postProcessBeforeInitialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(BeanPostProcessorImplTest.class.getSimpleName() + " :: " + bean.getClass().getName() + "#postProcessAfterInitialization");
return bean;
}
// 设置最高优先权
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
结果:
BeanPostProcessorImplTest
利用编辑器查找匹配 616 次。比未实现匹配次数多。
测试三
修改 BeanPostProcessorImplTest
,修改 Ordered
接口,为 PriorityOrdered
并且设置最高优先权
BeanPostProcessorImplTest
利用编辑器查找匹配 624 次,比实现Ordered
匹配次数多。
四、总结
1、BeanPostProcessor
bean 作用于 每个后续bean 的创建。提供自定义更改。可通过 Ordered
或者 PriorityOrdered
接口设置 BeanPostProcessor
bean 在处理链中的位置。
2、对于普通bean,执行顺序是构造函数 -> postProcessBeforeInitialization -> @PostConstruct -> InitializingBean#afterPropertiesSet -> postProcessAfterInitialization
。