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


前言

在此继续分析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的实现逻辑时,我们已经做了大概流程的梳理。不过下一篇可以详细梳理下。

总结

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值