Spring源码学习:BeanPostProcessor注册和执行时机

2022-09-30 14:17:17

前言

后置处理器是Spring框架提供的对外扩展点,通过实现对应接口,可以对bean进行各种操作(bean定义bd进行修改或者对初始化前后的bean进行各种修改),其中之一是BeanPostProcessor,本文主要从源码角度了解BeanPostProcessor的原理和执行过程。

1 BeanPostProcessors作用

BeanPostProcessor作为Spring框架重要的扩展点,对外提供了对bean实例化后,操作的空间,主要是涉及到对bean执行初始化方法前后调用对应方法实现对bean的各种功能增强,比如spring aop是利用BeanPostProcessor实现的代理增强。

2 源码分析

BeanPostProcessor的主要分析应该包括两部分:

  1. 注册bd定义,实例化和注册对应的bean实例
  2. 判断执行各种BeanPostProcessor的执行时机

2.1 BeanPostProcessors注册时机

以AnnotationConfigApplicationContext为例,对BeanPostProcessor的注册在AbstractApplicationContext.refresh方法
注册后置处理器该方法最终调用的是下面方法进行的核心处理
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this)
主要逻辑完成三件事

  1. 注册eanPostProcessorChecker记录特定情况日志
  2. 对各种优先级BeanPostProcessor进行排序,注册
  3. 重新注册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的类和待处理的类

  1. 待处理的类
    待处理类
  2. MyPostProcessor
    后置处理器

输出结果
在这里插入图片描述
可以看出初始化前后拦截D做的操作

总结

本篇文章主要是对BeanPostProcessor作用、注册和执行时机源码进行了学习,并对如何使用BeanPostProcessor扩展做了一个测试。

  • 作者:LamaxiyaFc
  • 原文链接:https://blog.csdn.net/qq_36566262/article/details/123967297
    更新时间:2022-09-30 14:17:17