Spring源码阅读----Spring IoC之invokeBeanFactoryPostProcessors

概述

前面我们讲解了Spring Ioc容器的初始化步骤,以及BeanFactory和ApplicationContext两类容器的对比。我们继续对ApplicationContext容器展开解析。前面一节中的注释4,invokeBeanFactoryPostProcessors这段没有展开讲解,在这里展开。
invokeBeanFactoryPostProcessors方法会实例化和调用所有 BeanFactoryPostProcessor(包括其子类 BeanDefinitionRegistryPostProcessor,前文的末尾我们提到的spring-mybaits包中的MapperScannerConfigurer类就是实现了这个接口,我们也可以在项目中自定义创建自己的类去实现这些接口),PostProcessor后置处理器其实已经体现了AOP设计思想。

BeanFactoryPostProcessor 接口
我们得知道BeanFactoryPostProcessor 是干嘛用的,这个接口是在BeanFactory初始化过程中,对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。

BeanDefinitionRegistryPostProcessor
继承了 BeanFactoryPostProcessor,它比 BeanFactoryPostProcessor 的优先级更高,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。
比如,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。

invokeBeanFactoryPostProcessors方法解析

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		//注释1 getBeanFactoryPostProcessors(): 获取当前应用上下文 beanFactoryPostProcessors 变量值
		// 注释2 invokeBeanFactoryPostProcessors(): 实例化并调用所有已注册的 BeanFactoryPostProcessor 后处理器
		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()));
		}
	}

这里主要看

  • 注释1,获取当前应用上下文 beanFactoryPostProcessors 变量值(见源码1解析)
  • 注释2, 实例化并调用所有已注册的 BeanFactoryPostProcessor 后处理器(见源码2解析)

**【源码1解析】,getBeanFactoryPostProcessors方法:

	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}

在初始化过程中我们发现这里默认就是空值,那思考一下有get,是不是有add方法呢?有的,这里有个addBeanFactoryPostProcessor方法,用来添加自定义的BeanFactoryPostProcessor,具体用法如下:

//假设我有个TestBeanFactoryPostProcessor,它实现了BeanDefinitionRegistryPostProcessor接口
public class TestBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor{
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("Test BeanFactory Post Processor execute time2");
	}

	public void postProcessBeanDefinitionRegistry(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("Test BeanFactory Post Processor execute time1");
	}
}

//新建一个 ApplicationContextInitializer 的实现类 SpringApplicationContextInitializer ,并在 initialize 方法中写我们的逻辑

public class SpringApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
 
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        TestBeanDefinitionRegistryPostProcessor   testBeanDefinitionRegistryPostProcessor = new TestBeanDefinitionRegistryPostProcessor();
        // 将自定义的firstBeanDefinitionRegistryPostProcessor添加到应用上下文中
        applicationContext.addBeanFactoryPostProcessor(testBeanDefinitionRegistryPostProcessor);
        // ...自定义操作
        System.out.println("SpringApplicationContextInitializer#initialize");
    }

将 SpringApplicationContextInitializer 作为初始化参数 contextInitializerClasses 配置到 web.xml 中

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>
        com.zhlab.ssm.demo.web.SpringApplicationContextInitializer
    </param-value>
</context-param>

这样在启动应用时,TestBeanDefinitionRegistryPostProcessor 就会被getBeanFactoryPostProcessors方法获取了。

【源码2解析】,PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法:

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

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();
		// beanFactory 由obtainFreshBeanFactory方法创建
                //注释1. 默认使用的是 DefaultListableBeanFactory,属于 BeanDefinitionRegistry
                // true
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			// 定义两个PostProcessor后处理器列表
			//分别存放BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
                        
			// 注释2. 处理传入参数中的 List<BeanFactoryPostProcessor> :beanFactoryPostProcessors
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                                
			    // 注释2-1 BeanDefinitionRegistryPostProcessor类型
			    // 先执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
  			     //再添加到registryProcessors
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
                
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
			    // 注释2-2 BeanFactoryPostProcessor类型,添加到regularPostProcessors
				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.
			//  用于保存本次要执行的BeanDefinitionRegistryPostProcessor
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			// 注释3.  首先,调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类。分步骤来看:
                       
			//注释3-1. 获取实现BeanDefinitionRegistryPostProcessor接口的Bean的beanName,下边遍历这些beanName
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
			    // 注释3-2. 如果实现了PriorityOrdered接口,就获取该bean实例,添加到currentRegistryProcessors中
			    // 并把该bean的名字加入到processedBeans集合中,避免重复
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}

			// 注释3-3. 对currentRegistryProcessors中的后置处理器进行排序,然后添加到registryProcessors
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);

			// 注释3-4. 遍历currentRegistryProcessors
			//执行 definitionRegistryPostProcessor 接口的方法 :postProcessBeanDefinitionRegistry
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			// 注释3-5. 清空currentRegistryProcessors
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			// 注释4.  接着,调用所有实现Ordered接口的BeanDefinitionRegistryPostProcessor实现类。过程同注释3
			//注释4-1. 获取实现BeanDefinitionRegistryPostProcessor接口的Bean的beanName,下边遍历这些beanName
			//为什么重新查找一次?
			//因为执行完上面的BeanDefinitionRegistryPostProcessor,可能会新增了其他的BeanDefinitionRegistryPostProcessor
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
			    // 注释4-2. 如果没在processedBeans集合中,并实现了Ordered接口,就获取该bean,添加到currentRegistryProcessors中
			    // 并把该bean的名字加入到processedBeans集合中,避免重复
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}

			// 注释4-3. 对currentRegistryProcessors中的后置处理器进行排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);

			// 注释4-4. 遍历currentRegistryProcessors
			//执行 definitionRegistryPostProcessor 接口的方法 :postProcessBeanDefinitionRegistry
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

			// 4-5清空currentRegistryProcessors
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			//注释5. 最后,调用所有其他BeanDefinitionRegistryPostProcessors,直到不再出现其他的为止
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;

				//找出所有实现BeanDefinitionRegistryPostProcessor接口的类
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
                                        //若还未加入到processedBeans集合中,则获取该bean并加入到currentRegistryProcessors里,并把其名加入processedBeans集合
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}

				//对currentRegistryProcessors中的后置处理器进行排序
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);

				// 遍历currentRegistryProcessors
				//执行 definitionRegistryPostProcessor 接口的方法 :postProcessBeanDefinitionRegistry
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

				//清空currentRegistryProcessors
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			// 注释6. 执行 postProcessBeanFactory 回调方法
			//注释6-1.调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry回调方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);

			//注释6-2.调用普通的BeanFactoryPostProcessor的postProcessBeanFactory 回调方法
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

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

		// 到这里 , 入参beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已经全部处理完毕,
		// 下面开始处理容器中的所有BeanFactoryPostProcessor

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		// 不要在这里初始化 factoryBean:我们需要保留所有常规 bean 未初始化,以便让 beanFactoryPostProcessors应用它们
		// 注释 7.  找出所有实现BeanFactoryPostProcessor接口的类
		在这个步骤中,我们自定义的 testBeanFactoryPostProcessor 才真正注册并执行
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		//用于存放实现了PriorityOrdered接口的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();

		//用于存放实现了Ordered接口的BeanFactoryPostProcessor
		List<String> orderedPostProcessorNames = new ArrayList<>();

		//用于存放普通BeanFactoryPostProcessor的beanName
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();

		// 注释7-1 遍历postProcessorNames
		// 将BeanFactoryPostProcessor按实现PriorityOrdered、实现Ordered接口、普通三种区分
		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.
		// 注释8. 调用所有实现PriorityOrdered接口的BeanFactoryPostProcessor
		// 注释8-1. 对priorityOrderedPostProcessors排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// 注释8-2. 遍历priorityOrderedPostProcessors
  		// 执行BeanFactoryPostProcessor接口的方法:postProcessBeanFactory
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		// 注释9. 然后,调用所有实现Ordered接口的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {

			//获取postProcessorName对应的bean实例, 添加到orderedPostProcessors, 准备执行
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		//注释9-1. 对orderedPostProcessors排序
		sortPostProcessors(orderedPostProcessors, beanFactory);

		// 注释9-2. 遍历orderedPostProcessors
  		// 执行BeanFactoryPostProcessor接口的方法:postProcessBeanFactory
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		// 注释10. 最后,调用所有剩下的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {

			//注释10-1. 获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}

		// 注释10-2. 遍历nonOrderedPostProcessors
  		// 执行BeanFactoryPostProcessor接口的方法:postProcessBeanFactory
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		// 清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
		// 因为后处理程序可能已经修改了原始元数据,例如替换值中的占位符
		beanFactory.clearMetadataCache();
	}

好了,因为代码比较长,所以整个调用过程都在注释里写清晰了。

注释3-2那里,通过ppName获取bean实例,我们前文中提到过BeanFactory中的bean是在获取的时候会初始化bean实例,是不是这里跟BeanFactory有关呢?我们之后单独讲一篇关于getBean的解析。

排序方法、执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry和执行BeanFactoryPostProcessor的postProcessBeanFactory方法比较简单:

	//排序
	private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
		Comparator<Object> comparatorToUse = null;
		if (beanFactory instanceof DefaultListableBeanFactory) {
			comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
		}
		if (comparatorToUse == null) {
			comparatorToUse = OrderComparator.INSTANCE;
		}
		postProcessors.sort(comparatorToUse);
	}

	/**
	 * 执行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
	 */
	private static void invokeBeanDefinitionRegistryPostProcessors(
			Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

		for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanDefinitionRegistry(registry);
		}
	}

	/**
	 * 执行BeanFactoryPostProcessor的postProcessBeanFactory方法
	 */
	private static void invokeBeanFactoryPostProcessors(
			Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {

		for (BeanFactoryPostProcessor postProcessor : postProcessors) {
			postProcessor.postProcessBeanFactory(beanFactory);
		}
	}

BeanDefinitionRegistryPostProcessor 的扩展使用场景

在前面一文中的末尾我们提到了mybatis-spring.jar包中的MapperScannerConfigurer这个类,它就是一个实现了BeanDefinitionRegistryPostProcessor接口的类,查看一下它的实现源码:

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {

//...前面省略
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        if (this.processPropertyPlaceHolders) {
            this.processPropertyPlaceHolders();
        }

        ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
        scanner.setAddToConfig(this.addToConfig);
        scanner.setAnnotationClass(this.annotationClass);
        scanner.setMarkerInterface(this.markerInterface);
        scanner.setSqlSessionFactory(this.sqlSessionFactory);
        scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
        scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
        scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
        scanner.setResourceLoader(this.applicationContext);
        scanner.setBeanNameGenerator(this.nameGenerator);
        scanner.registerFilters();
        scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ",; \t\n"));
    }

//...后面省略
}

这样它就会在初始化的时候,扫描basePackage配置路径。所以参考这个场景,我们在写自己的一些依赖于spring的框架时候,也可以写一些自定义的PostProcessor。

总结

  • 整个 invokeBeanFactoryPostProcessors 方法围绕BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor两个接口在操作(BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor)。
    BeanDefinitionRegistryPostProcessor 主要用来在常规 BeanFactoryPostProcessor 检测开始之前注册其他 Bean 定义,说的简单点,就是 BeanDefinitionRegistryPostProcessor 具有更高的优先级,执行顺序在 BeanFactoryPostProcessor 之前。
  • 三种postProcessor:
    入参 beanFactoryPostProcessors:来自 AbstractApplicationContext 类的 beanFactoryPostProcessors 属性值,也就是在之前已经添加到 beanFactoryPostProcessors 中的 BeanFactoryPostProcessor。
    BeanDefinitionRegistryPostProcessor 接口实现类:实现了 BeanDefinitionRegistryPostProcessor 接口,并且注册到 Spring IoC容器中。
    常规 BeanFactoryPostProcessor 接口实现类:实现了 BeanFactoryPostProcessor 接口,并且注册到 Spring IoC容器中。
  • 对三种postProcessor排序,按优先级调用其接口方法的实现。
  • PriorityOrdered 和 Ordered 是两个比较重要的排序接口。
  • 常见的 框架或者中间件,经常使用 BeanFactoryPostProcessor 来进行扩展,例如上面讲的 Mybatis,因此了解 BeanFactoryPostProcessor 的原理会对之后理解其他框架如何跟Spring关联会有帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值