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

前言

后置处理器是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(new BeanPostProcessorChecker(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 = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//getBean--实例化,初始化bd
				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);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		//排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		//实例化注册
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		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);

		// Now, register all regular BeanPostProcessors.
		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);

将后置处理器按照以下四类进行排序添加
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) {
			throw new BeanCreationException(
					(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扩展做了一个测试。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LamaxiyaFc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值