Spring源码学习(四):容器ApplicationContext的refresh(2)- 执行BeanFactoryPostProcessor

文章目录

  • 前言
  • 一、BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor是什么
  • 二、Spring执行这些PostProcessor的步骤
    • 1. BeanDefinitionRegistryPostProcessor优先级高
    • 2. 开始执行Spring容器里的BeanDefinitionRegistryPostProcessor
      • 2.1 执行了PriorityOrder接口的BeanDefinitionRegistryPostProcessor
      • 2.2 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
      • 2.3 ConfigurationClassParser
  • 总结


前言

在此继续分析spring源码,上一篇讲到了ApplicationContext.refresh里的基础语句。今天进入比较重要的阶段:

// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

一、BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor是什么

此处不做过多介绍,想理解这个具体作用的,可以参见这篇拙作

二、Spring执行这些PostProcessor的步骤

1. BeanDefinitionRegistryPostProcessor优先级高

从invokeBeanFactoryPostProcessors一路debug下去,会到PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors,这也是Spring初始执行BeanFactoryPostProcessor的精髓了。

		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);
			}
		}

可以发现把传进来的BeanPostProcessor,凡是BeanDefinitionPostProcessor类型的,先执行一遍,同时放到registryProcessors里面,而普通的BeanFactoryPostProcessor放入到regularPostProcessors里面

2. 开始执行Spring容器里的BeanDefinitionRegistryPostProcessor

2.1 执行了PriorityOrder接口的BeanDefinitionRegistryPostProcessor

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				// 筛选实现了PriorityOrdered接口的
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					// 注意此处的getBean,其实已经开始使用IOC的bean实例化周期了 
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					// 防止某个BeanFactoryPostProcessor被重复执行,所以获取了的,就保存起来
					processedBeans.add(ppName);
				}
			}
			// 排序,其实此处Spring容器就提供了一个ConfigurationClassPostProcessor,所以排序方法,其实没走实现
			// 而且这个类的getOrder方法返回的是Integer.MAX_VALUE
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			// 调用BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

2.2 ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

这个方法也就是Spring中的重中之重了。
这个方法里调用了processConfigBeanDefinitions

		// 获取已放入到容器中的所有BeanDefinition的name,我们的xxxApplication当然在里面
		String[] candidateNames = registry.getBeanDefinitionNames();

		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			// 此处判断BeanDef上的某个标记CONFIGURATION_CLASS_ATTRIBUTE是否存在
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				// log
			}
			/** 
			 *	实际上进行进行该标记的处理逻辑在此,其实就是区分了下@Configuration的重要地位,加了这个注解的
			 * CONFIGURATION_CLASS_ATTRIBUTE被标记为full,而加了@Component、@ComponentScan、@Import
			 * @ImportResource、@Bean注解的CONFIGURATION_CLASS_ATTRIBUTE被设置为lite
			 * 此处该标记的作用其实还是蛮重要的,只不过大多数时候我们写代码不会触发其出问题
			**/
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

2.3 ConfigurationClassParser

parser.parse(candidates);方法里完成了BeanDefinition的扫描以及register,其实在这篇文章里面为了介绍@EnableAutoConfiguration的实现逻辑时,我们已经做了大概流程的梳理。不过下一篇可以详细梳理下。

总结

这一篇内容较少,最近耐心不足。需要坚持~

你可能感兴趣的:(spring,源码分析,spring,java)