Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析

这篇具有很好参考价值的文章主要介绍了Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、简介

Spring有两种类型的后置处理器,分别是 BeanFactoryPostProcessorBeanPostProcessor ,这里再贴出我画的 Spring 启动过程,可以看看这两种后置处理器在 Spring 启动过程中位置。

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

1、BeanFactoryPostProcessor

BeanFactoryPostProcessorpostProcessBeanFactory 方法在 Spring 容器启动时被调用,可以对整个容器中的 BeanDefinition (Bean 定义)进行处理,BeanFactoryPostProcessor 还有个子接口 BeanDefinitionRegistryPostProcessor ,其 postProcessBeanDefinitionRegistry 方法也可以对 BeanDefinition 进行处理的,但两个的侧重点不一样, BeanDefinitionRegistryPostProcessor 侧重于创建自定义的 BeanDefinition,而 BeanFactoryPostProcessor 侧重于对已有的 BeanDefinition 进行修改。

2、BeanPostProcessor

BeanPostProcessor 是在 Bean 初始化方法调用前后,对 Bean 进行一些预处理或后处理,这个接口有两个方法,分别是 postProcessBeforeInitializationpostProcessAfterInitialization,分别用来执行预处理和后处理。

二、BeanFactoryPostProcessor 源码解析

处理 BeanFactoryPostProcessor 的源码在哪里呢,我们先找到 Spring 的核心方法 refresh 方法(在 AbstractApplicationContext 类里),在里面找到 invokeBeanFactoryPostProcessors 方法

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

跟进去这个方法

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

在跟进到 PostProcessorRegistrationDelegate 类的 invokeBeanFactoryPostProcessors 方法里,就到了核心处理逻辑了,先列出这个方法的代码

public static void invokeBeanFactoryPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

	// Invoke BeanDefinitionRegistryPostProcessors first, if any.
	Set<String> processedBeans = new HashSet<>();

	if (beanFactory instanceof BeanDefinitionRegistry) {
		BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
		List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
		List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

		for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
			if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
				BeanDefinitionRegistryPostProcessor registryProcessor =
						(BeanDefinitionRegistryPostProcessor) postProcessor;
				registryProcessor.postProcessBeanDefinitionRegistry(registry);
				registryProcessors.add(registryProcessor);
			}
			else {
				regularPostProcessors.add(postProcessor);
			}
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		// Separate between BeanDefinitionRegistryPostProcessors that implement
		// PriorityOrdered, Ordered, and the rest.
		List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

		// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
		postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
		for (String ppName : postProcessorNames) {
			if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
				currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
				processedBeans.add(ppName);
			}
		}
		sortPostProcessors(currentRegistryProcessors, beanFactory);
		registryProcessors.addAll(currentRegistryProcessors);
		invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
		currentRegistryProcessors.clear();

		// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
		boolean reiterate = true;
		while (reiterate) {
			reiterate = false;
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
					reiterate = true;
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
		}

		// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
		invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
	}

	else {
		// Invoke factory processors registered with the context instance.
		invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
	}

	// Do not initialize FactoryBeans here: We need to leave all regular beans
	// uninitialized to let the bean factory post-processors apply to them!
	String[] postProcessorNames =
			beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

	// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
	for (String ppName : postProcessorNames) {
		if (processedBeans.contains(ppName)) {
			// skip - already processed in first phase above
		}
		else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
		}
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);
		}
	}

	// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

	// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
	List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : orderedPostProcessorNames) {
		orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	sortPostProcessors(orderedPostProcessors, beanFactory);
	invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

	// Finally, invoke all other BeanFactoryPostProcessors.
	List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
	for (String postProcessorName : nonOrderedPostProcessorNames) {
		nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
	}
	invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

	// Clear cached merged bean definitions since the post-processors might have
	// modified the original metadata, e.g. replacing placeholders in values...
	beanFactory.clearMetadataCache();
}

这段代码比较长,我们可以分成两部分来看,前半部分处理 BeanDefinitionRegistryPostProcessors 接口的实现类,后半部分处理 BeanFactoryPostProcessor 接口的实现类,我们先看 BeanDefinitionRegistryPostProcessors 接口的处理流程

1、BeanDefinitionRegistryPostProcessor 接口实现类的处理流程

首先创建了一个名叫 processedBeansHashSet

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

是为了记录处理过的 PostProcessor 的名字,目的是防止重复处理,然后下面对 beanFactory 的类型进行了判断,如果是 BeanDefinitionRegistry 类型,会有一大段的处理逻辑,如果不是,就调用 invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); 方法

if (beanFactory instanceof BeanDefinitionRegistry) {
	...
}

else {
	// Invoke factory processors registered with the context instance.
	invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}

这个方法,其实就是循环执行所有 PostProcessorpostProcessBeanFactory 方法,我们再来看如果是 BeanDefinitionRegistry 类型,是怎么处理的,先看第一段

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

这一段是将传进来的参数 BeanFactoryPostProcessor 集合进行区分,分成 BeanDefinitionRegistryPostProcessor 类型(后面简称 BDRPP)和非 BeanDefinitionRegistryPostProcessor 类型,其实就是 BeanFactoryPostProcessor 类型(后面简称 BFPP),并执行了 BDRPP 类型的 postProcessBeanDefinitionRegistry 方法,并且,把两种类型分别添加到了两个集合里 registryProcessorsregularPostProcessors,继续往下看

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

这一段,先声明了一个 BDRPP 类型的集合,用于存放在 Spring 容器里找到的 BDRPP,然后从 Spring 容器里找到所有 BDRPP 的名字,循环并找到实现了 PriorityOrdered 接口的 BDRPP,排序,添加到之前定义区分 BDRPPBFPP 的集合 registryProcessors 里,然后执行了这些实现了 PriorityOrdered 接口的 BDRPP postProcessBeanDefinitionRegistry 方法,下面以同样的方式处理实现了 Ordered 接口的 BDRPP,这里先科普下 PriorityOrderedOrdered

PriorityOrdered Ordered 是 Spring 框架中用于定义 Bean 的加载顺序的接口。而 PriorityOrderedOrdered 的子类,实现了这两个接口的类,需要实现一个 getOrder() 方法,返回一个 int 值,这个值越大,优先级就越低,而实现了 PriorityOrdered 接口的 Bean 的加载顺序会优先于实现了 Ordered 接口的Bean,且两者都优先于没实现这两个接口的 Bean

所以,这里先处理的实现了 PriorityOrdered 接口的 BDRPP ,再处理了实现了 Ordered 接口的 BDRPP ,有的人会好奇哦,为什么上面已经调用过一次 beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);,下面为什么还要再调一次,这不是重复代码了吗,其实不是,执行了 BDRPPpostProcessBeanDefinitionRegistry 方法,有可能会产生新的 BDRPP ,所以需要再重新取一次,继续看下面的代码

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

知道了执行了 BDRPPpostProcessBeanDefinitionRegistry 方法,有可能会产生新的 BDRPP ,这段就好理解了,一直循环获取 BDRPP,执行其 postProcessBeanDefinitionRegistry 方法,直到不产生新的 BDRPP 为止

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

最后,因为 BDRPPBFPP 的子类,所以也是需要执行 BFPP 里的 postProcessBeanFactory 方法的,但是 BDRPP 的先执行,BFPP 的后执行。

到此 BDRPP 的处理完了,下面看 BFPP

2、BeanFactoryPostProcessor 接口实现类的处理流程

看完 BeanDefinitionRegistryPostProcessor 之后,BeanFactoryPostProcessor(后面简称 BFPP)的处理流程就比较简单了,先看第一段代码

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

获取 Spring 容器里所有 BFPP 类型的 Bean,然后分成三类,分别是实现了 PriorityOrdered 接口的,实现了 Ordered 接口的,其他(也就是不需要排序的),这里需要注意,因为获取 BFPP 类型的 Bean,会将 BDRPP 类型的也获取到,因为 BDRPPBFPP 的子类嘛,所以之前处理过的 BDRPP 需要跳过,继续看下面

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

这边就很好理解了,按照 PriorityOrdered > Ordered > 其他,的顺序依次执行 postProcessBeanFactory 方法

3、总结

总结一下执行顺序

  1. 先执行了 BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry 方法,按照顺序 PriorityOrdered > Ordered > 其他;
  2. 再执行了 BeanDefinitionRegistryPostProcessorpostProcessBeanFactory 方法;
  3. 最后执行 BeanFactoryPostProcessorpostProcessBeanFactory 方法,按照顺序 PriorityOrdered > Ordered > 其他;

三、BeanPostProcessor 源码解析

处理 BeanPostProcessor (后面简称 BPP)的源码在哪里呢,我们知道 BPP 是在 Bean 实例化过程中,init 方法执行前后调用的,入口在 Spring 的核心方法 refresh 方法中的 finishBeanFactoryInitialization(beanFactory); 方法里,里面嵌套很多方法,我们直接来到创建 Bean 的核心方法里,也就是 AbstractAutowireCapableBeanFactory 类的 doCreateBean 方法,在这个方法里找到 exposedObject = initializeBean(beanName, exposedObject, mbd); 这句

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端

在对 Bean 进行实例化和属性填充之后,就会执行这个方法,进一步完成 Bean 的初始化,我们看看这个方法

Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析,源码学习,Spring,Java,spring,java,后端
可以看到在执行 init 方法前后,分别执行了 applyBeanPostProcessorsBeforeInitializationapplyBeanPostProcessorsAfterInitialization 方法,这两个方法里,循环了所有的 BPP,调用了其 postProcessBeforeInitializationpostProcessAfterInitialization 方法。文章来源地址https://www.toymoban.com/news/detail-541506.html

到了这里,关于Spring后置处理器BeanFactoryPostProcessor与BeanPostProcessor源码解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Jmeter后置处理器——JSON提取器

    Jmeter后置处理器——JSON提取器

    目录 1、简介  2、使用步骤         1)添加线程组         2)添加http请求         3) 添加JSON提取器 1、简介         JSON是一种简单的数据交换格式,允许互联网应用程序快速传输数据。JSON提取器可以从JSON格式响应数据中提取数据、简化从JSON原始数据中提取特

    2024年01月16日
    浏览(9)
  • 【JMeter】后置处理器的分类以及场景介绍

    【JMeter】后置处理器的分类以及场景介绍

    1.常用后置处理器的分类 Json提取器 针对响应体的返回结果是 json格式 的 会自动生成新的变量名为【提取器中 变量名_MatchNr 】,取到的个数由jsonpath expression取到的个数决定 可以当作普通变量调用,调用语法:${ 提取器中 变量名_MatchNr } 正则表达式提取器 返回结果是 任何数

    2024年02月05日
    浏览(12)
  • jmeter-BeanShell预处理器与BeanShell后置处理器的使用

    jmeter-BeanShell预处理器与BeanShell后置处理器的使用

    BeanShell是一个小型嵌入式Java源代码解释器,具有对象脚本语言特性,能够动态地执行标准JAVA语法,并利用在JavaScript和Perl中常见的松散类型、命令、闭包等通用脚本来对其进行拓展。 前置处理器:请求发送之前对请求参数做一些处理 后置处理器:请求发送完成之后对响应数

    2023年04月17日
    浏览(14)
  • 【Jmeter】Request1输出作为Request2输入-后置处理器

    【Jmeter】Request1输出作为Request2输入-后置处理器

    【Jmeter】基础介绍-详细 接上文,继续介绍Jmeter,本文关注点为如何解决上文中提到的第一个问题,即: 需要实现Request1的返回作为Request2的RequestBody或Header Jmeter支持后置处理器,即对http请求(或其他取样器)的返回值进行提取并赋值给变量。 本例中从Request1的ResponseBody中提

    2023年04月20日
    浏览(13)
  • Spring MVC异常处理【单个控制异常处理器、全局异常处理器、自定义异常处理器】

    Spring MVC异常处理【单个控制异常处理器、全局异常处理器、自定义异常处理器】

    目录 一、单个控制器异常处理 1.1 控制器方法 1.2 编写出错页面 1.3 测试结果 二、全局异常处理 2.1 一个有异常的控制器类 2.2 全局异常处理器类 2.3 测试结果  三、自定义异常处理器 3.1 自定义异常处理器 3.2 测试结果 往期专栏文章相关导读  1. Maven系列专栏文章 2. Mybatis系列

    2024年02月16日
    浏览(14)
  • Spring Boot 容器扩展BeanFactoryPostProcessor、BeanPostProcessor、 BeanDefinitionRegistryPostProcessor用法和解析

    Spring Boot 容器扩展BeanFactoryPostProcessor、BeanPostProcessor、 BeanDefinitionRegistryPostProcessor用法和解析

    之所以在企业级应用中Spring 到Spring Boot 一直立于不败之地,保持火热,其中很关键的一个点是,它的扩展简直太强大了,上一篇,我们聊了一下 Spring Boot整个生命周期中的扩展点,,比如 SpringApplicationRunListener 可以监听应用的各个阶段。本文我们聊聊,Spring 容器上的扩展。

    2024年02月11日
    浏览(12)
  • Spring异常处理器

    Spring异常处理器

     问题:   程序允许不免的在各层都可能会产生异常,我们该如何处理这些异常? 如果只是在方法里面单独使用 try… catch… 语句去一个一个的进行捕捉处理的话,那毫无疑问是不现实的,因为异常数量是非常庞大的并且对于异常的出现种类是不可预料的,于是我们可以使用

    2024年02月13日
    浏览(15)
  • Spring MVC 异常处理器

    Spring MVC 异常处理器

    如果不加以异常处理,错误信息肯定会抛在浏览器页面上,这样很不友好,所以必须进行异常处理。 系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图: 编写controller 在index.jsp里面定义超链接

    2024年01月22日
    浏览(17)
  • spring框架_常见工厂后处理器

    spring框架_常见工厂后处理器

    ConfigurationClassPostProcessor :用于解析@ComponentScan @Bean @Import @ImportResource MapperSacnnerConfigurer :相当于Mybatis的@MapperScanner 用于解析被标注的@Mapper接口 @mapper 注解的解析:@mapper注解是mybatis提供的,用于标明一个接口,spring自然无法管理接口,要将这个接口转化为一个bean加入到beanfa

    2024年02月05日
    浏览(59)
  • Spring MVC配置全局异常处理器!!!

    Spring MVC配置全局异常处理器!!!

    为什么要使用全局异常处理器:如果不加以异常处理,错误信息肯定会抛在浏览器页面上,这样很不友好,所以必须进行异常处理。 系统的dao、service、controller出现都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,如下图: 结果展示:  

    2024年01月15日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包