当前位置: 首页 > 编程笔记 >

Spring的BeanFactoryPostProcessor接口示例代码详解

方建明
2023-03-14
本文向大家介绍Spring的BeanFactoryPostProcessor接口示例代码详解,包括了Spring的BeanFactoryPostProcessor接口示例代码详解的使用技巧和注意事项,需要的朋友参考一下

接口简介

BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。

BeanDefinitionRegistryPostProcessor 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean html" target="_blank">定义。特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。

注意点:通过BeanDefinitionRegistryPostProcessor 注册的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法将得不到调用,具体的原因会在下面的代码中解释。

BeanFactoryPostProcessor 接口调用机制

BeanFactoryPostProcessor 接口的调用在 AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

进入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法:

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   // 用于存放已经处理过的Bean名字
		Set<String> processedBeans = new HashSet<>();
   // 一般会进入这个判断
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    // 所谓的regularPostProcessors就是指实现BeanFactoryPostProcessor接口的Bean
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    // 所谓的registryProcessors就是指实现BeanDefinitionRegistryPostProcessor接口的Bean
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    // 这边遍历的是通过ApplicationContext接口注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口
    // 需要和BeanFactory中BeanDefinitionMap中的BeanFactoryPostProcessor接口区分开
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
      //如果是BeanDefinitionRegistryPostProcessor,则先进行postProcessBeanDefinitionRegistry处理,这个方法一般进行BeanDefinition注册,从这边可以看出BeanDefinitionRegistryPostProcessor接口的方法先调用,所以优先级高于BeanFactoryPostProcessor
      // 通过这个代码可以看出,通过ApplicationContext直接注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor并不支持Order接口,而是根据注册的顺序执行
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
      // 保存这个BeanDefinitionRegistryPostProcessor,因为还要执行这个类的BeanFactoryPostProcessor方法;
					registryProcessors.add(registryProcessor);
				}
				else {
      // 保存,后面还要执行这个类的BeanFactoryPostProcessor方法;
					regularPostProcessors.add(postProcessor);
				}
			}

			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    // 这边获取的是BeanFactory中的BeanDefinitionRegistryPostProcessor
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
     //先处理PriorityOrdered标注的BeanDefinitionRegistryPostProcessor
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
      //将其标记为已经处理,防止重复处理
					processedBeans.add(ppName);
				}
			}
    // 将其排序,以便按顺序处理
			sortPostProcessors(currentRegistryProcessors, beanFactory);
    // 将其保存,以便处理这个类的BeanFactoryPostProcessor方法
			registryProcessors.addAll(currentRegistryProcessors);
    // 执行BeanDefinitionRegistryPostProcessor接口方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    // 清除,以便开始处理@Order标注的注解
			currentRegistryProcessors.clear();
  
    // 注意:这边重新获取BeanDefinitionRegistryPostProcessor是有深意的,因为上面在处理@PriorityOrdered标注的BeanDefinitionRegistryPostProcessor时可能又注入了新的BeanDefinitionRegistryPostProcessor。
			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();

    // 处理不标注注解的BeanDefinitionRegistryPostProcessor
			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();
			}

			// 调用postProcessBeanFactory 方法,所以BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法的优先级要高。
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

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

		// 开始处理BeanFactoryPostProcessor接口
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// 也是按照@PriorityOrdered @Ordered 和普通的方式进行处理
		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);
			}
		}
   // 先执行@PriorityOrdered标注的接口
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
   // 处理@Order标注的类
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
    // 这边通过名字重新拿了Bean,应该是怕上面的处理改变了Bean
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 最后调用普通的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		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();
	}

简单总结

上面的方法看起来很长很复杂,但其实干的事情并不多,就调用了BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口的实现。这边再简单总结下具体的过程:

step1:执行通过ApplicationContext#addBeanFactoryPostProcessor()方法注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。

具体过程如下:假如通过ApplicationContext注册了一个BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,那么会先执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,但是BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法和BeanFactoryPostProcessor的postProcessBeanFactory方法暂时都不会在这步执行。

另外需要注意的是:通过ApplicationContext注册的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都不支持@PriorityOrdered和@Ordered顺序处理,而是按照我们添加的顺序处理

step2:处理BeanFactory中的BeanDefinitionRegistryPostProcessor,处理的顺序是先处理@PriorityOrdered标注的,再处理@Ordered标注的,最后处理普通的BeanDefinitionRegistryPostProcessor。到这边,所有BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法都已经调用完毕,下面就开始处理BeanFactoryPostProcessor的postProcessBeanFactory方法。

step3:调用BeanDefinitionRegistryPostProcessor实现的postProcessBeanFactory方法(因为BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)

step4:调用通过ApplicationContext#addBeanFactoryPostProcessor()注册的“单纯”的BeanFactoryPostProcessor

step5:调用BeanFactory中的BeanFactoryPostProcessor,调用顺序也是按照@PriorityOrdered和@Ordered顺序处理,没有这两个注解的最后处理。

好了,到这边BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口就已经处理完了。后面我们会拿ConfigurationClassPostProcessor 这个特殊的BeanDefinitionRegistryPostProcessor做列子讲下具体流程,这边只是介绍BeanFactoryPostProcessor的调用机制。

到此这篇关于Spring的BeanFactoryPostProcessor接口的文章就介绍到这了,更多相关Spring BeanFactoryPostProcessor接口内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!

 类似资料:
  • 本文向大家介绍Springmvc Controller接口代码示例,包括了Springmvc Controller接口代码示例的使用技巧和注意事项,需要的朋友参考一下 Spring MVC Controller控制器,是MVC中的部分C,为什么是部分呢?因为此处的控制器主要负责功能处理部分: 收集、验证请求参数并绑定到命令对象; 将命令对象交给业务对象,由业务对象处理并返回模型数据; 返回Mode

  • 开源demo 目前提供了完整的Java版开源示例demo,便于您快速的熟悉Java开发工具包的使用及接口的调用。Java版demo 意见反馈 在开发过程中,您有任何问题或者建议,可直接与我们联系。 客服电话:400-161-0019 电子邮箱:service@qingtui.cn

  • 本文向大家介绍详解Java中接口的定义与实例代码,包括了详解Java中接口的定义与实例代码的使用技巧和注意事项,需要的朋友参考一下 Java中接口的定义详解 1、定义接口     使用interface来定义一个接口。接口定义同类的定义类似,也是分为接口的声明和接口体,其中接口体由常量定义和方法定义两部分组成。定义接口的基本格式如下: 修饰符:可选,用于指定接口的访问权限,可选值为public。如

  • 本文向大家介绍Android SQLite详解及示例代码,包括了Android SQLite详解及示例代码的使用技巧和注意事项,需要的朋友参考一下 在Android中使用SQLite数据库的入门指南,打算分下面几部分与大家一起分享, 1、什么是SQLite 2、Android中使用SQLite 一、什么是SQLite SQLite是一款开源的、轻量级的、嵌入式的、关系型数据库。它在2000年由D.

  • 本文向大家介绍AngularJS Ajax详解及示例代码,包括了AngularJS Ajax详解及示例代码的使用技巧和注意事项,需要的朋友参考一下 AngularJS提供$http控制,可以作为一项服务从服务器读取数据。服务器可以使一个数据库调用来获取记录。 AngularJS需要JSON格式的数据。一旦数据准备好,$http可以用以下面的方式从服务器得到数据。 在这里,data.txt中包含的学

  • 本文向大家介绍AngularJs Scope详解及示例代码,包括了AngularJs Scope详解及示例代码的使用技巧和注意事项,需要的朋友参考一下 一、什么是Scope?   scope(http://code.angularjs.org/1.0.2/docs/api/ng.$rootScope.Scope)是一个指向应用model的object。它也是expression(http://ww