目录
前言
后置处理器是Spring框架提供的对外扩展点,通过实现对应接口,可以对bean进行各种操作(bean定义bd进行修改或者对初始化前后的bean进行各种修改),其中之一是BeanPostProcessor,本文主要从源码角度了解BeanPostProcessor的原理和执行过程。
1 BeanPostProcessors作用
BeanPostProcessor作为Spring框架重要的扩展点,对外提供了对bean实例化后,操作的空间,主要是涉及到对bean执行初始化方法前后调用对应方法实现对bean的各种功能增强,比如spring aop是利用BeanPostProcessor实现的代理增强。
2 源码分析
BeanPostProcessor的主要分析应该包括两部分:
- 注册bd定义,实例化和注册对应的bean实例
- 判断执行各种BeanPostProcessor的执行时机
2.1 BeanPostProcessors注册时机
以AnnotationConfigApplicationContext为例,对BeanPostProcessor的注册在AbstractApplicationContext.refresh方法该方法最终调用的是下面方法进行的核心处理
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this)
主要逻辑完成三件事
- 注册eanPostProcessorChecker记录特定情况日志
- 对各种优先级BeanPostProcessor进行排序,注册
- 重新注册ApplicationListenerDetector,移动到处理器尾部
2.1.1 注册beanPostProcessorChecker
String[] postProcessorNames= beanFactory.getBeanNamesForType(BeanPostProcessor.class,true,false);// Register BeanPostProcessorChecker that logs an info message when// a bean is created during BeanPostProcessor instantiation, i.e. when// a bean is not eligible for getting processed by all BeanPostProcessors./**
* 目标总数:获取已经实例化的BeanPostProcessor+ 1(BeanPostProcessorChecker) + 已经注册的bd但是还未实例化
* BeanPostProcessorChecker作用:
* 在所有BeanPostProcessor实例化期间,如果有bean创建,则打印日志记录-该bean的初始化可能不能得到所有后置处理器的处理,
* 以为还有已经注册bd,但是未实例化的bd
*/int beanProcessorTargetCount= beanFactory.getBeanPostProcessorCount()+1+ postProcessorNames.length;
beanFactory.addBeanPostProcessor(newBeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
通过BeanPostProcessorChecker判断BeanPostProcessor注册期间是否有注册新的bean,检测逻辑如下图
通过this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount,判断是否已经完成所有BeanPostProcessor的注册
2.1.2 各种优先级BeanPostProcessor进行排序注册
该过程就是根据BeanPostProcessor实现的各种接口判断优先级,逻辑比较简单:
/**
* 将后置处理器按照以下四类进行排序添加
* 1. 实现PriorityOrdered接口
* 2. 实现Ordered接口
* 3. 实现MergedBeanDefinitionPostProcessor,内部后置处理器
* 4. 其它后置处理器
* 对上述的处理分别按照类别进行排序,然后添加到beanPostProcessors缓存中
*/List<BeanPostProcessor> priorityOrderedPostProcessors=newArrayList<>();List<BeanPostProcessor> internalPostProcessors=newArrayList<>();List<String> orderedPostProcessorNames=newArrayList<>();List<String> nonOrderedPostProcessorNames=newArrayList<>();for(String ppName: postProcessorNames){if(beanFactory.isTypeMatch(ppName,PriorityOrdered.class)){//getBean--实例化,初始化bdBeanPostProcessor pp= beanFactory.getBean(ppName,BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){
internalPostProcessors.add(pp);}}elseif(beanFactory.isTypeMatch(ppName,Ordered.class)){
orderedPostProcessorNames.add(ppName);}else{
nonOrderedPostProcessorNames.add(ppName);}}// First, register the BeanPostProcessors that implement PriorityOrdered.//排序sortPostProcessors(priorityOrderedPostProcessors, beanFactory);//实例化注册registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);// Next, register the BeanPostProcessors that implement Ordered.List<BeanPostProcessor> orderedPostProcessors=newArrayList<>(orderedPostProcessorNames.size());for(String ppName: orderedPostProcessorNames){BeanPostProcessor pp= beanFactory.getBean(ppName,BeanPostProcessor.class);
orderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){
internalPostProcessors.add(pp);}}sortPostProcessors(orderedPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, orderedPostProcessors);// Now, register all regular BeanPostProcessors.List<BeanPostProcessor> nonOrderedPostProcessors=newArrayList<>(nonOrderedPostProcessorNames.size());for(String ppName: nonOrderedPostProcessorNames){BeanPostProcessor pp= beanFactory.getBean(ppName,BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);if(ppinstanceofMergedBeanDefinitionPostProcessor){
internalPostProcessors.add(pp);}}registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);// Finally, re-register all internal BeanPostProcessors.sortPostProcessors(internalPostProcessors, beanFactory);registerBeanPostProcessors(beanFactory, internalPostProcessors);
将后置处理器按照以下四类进行排序添加
1. 实现PriorityOrdered接口
2. 实现Ordered接口
3. 实现MergedBeanDefinitionPostProcessor,内部后置处理器
4. 其它后置处理器
对上述的处理分别按照类别进行排序,然后添加到beanPostProcessors缓存中
注册逻辑如下,主要是根据bean工厂类型,有一个批量添加(底层CopyOnWriteArrayList复制加锁批量添加)的区别
2.1.3 重新注册ApplicationListenerDetector
由于在prepareBeanFactory时已经添加了ApplicationListenerDetector,这里之所以要重新添加是为了能够处理代理bean,主要代码就一句如下图
官方注释意思应该是拾取代理,从而放最后一个进行注册,对代理bean也能够进行处理,避免先执行而无法获取代理bean。
2.2 BeanPostProcessors执行时机
在创建bean,执行bean初始化前后执行具体是doCreateBean–>initializeBean这个方法
Object wrappedBean= bean;if(mbd==null||!mbd.isSynthetic()){// 处理初始化前执行postProcessBeforeInitialization
wrappedBean=applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try{//初始化invokeInitMethods(beanName, wrappedBean, mbd);}catch(Throwable ex){thrownewBeanCreationException((mbd!=null? mbd.getResourceDescription():null),
beanName,"Invocation of init method failed", ex);}if(mbd==null||!mbd.isSynthetic()){//处理初始化后执行postProcessAfterInitialization
wrappedBean=applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}
在执行初始化bean前后调用,调用函数如下就是根据添加顺序依次处理,这也是为什么需要把ApplicationListenerDetector放到末尾处理,以防止较早处理获取不到代理对象。
3 扩展示例
首先自定义一个实现BeanPostProcessor的类和待处理的类
- 待处理的类
- MyPostProcessor
输出结果
可以看出初始化前后拦截D做的操作
总结
本篇文章主要是对BeanPostProcessor作用、注册和执行时机源码进行了学习,并对如何使用BeanPostProcessor扩展做了一个测试。