spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配

spring-framework 版本:v5.3.19

前面研究了beanDefinition的注册,但也仅仅是注册这一动作。那么在spring容器启动的过程中,是何时/如何装配的?以及装配的bean是如何注入的?
(考虑到xml方式基本不用了以及篇幅问题,所以本篇只看注解方式AnnotationConfigApplicationContext。)

文章目录

  • 何时装配
    • beanFactoryPostProcessor的执行入口
    • ConfigurationClassPostProcessor的注册
  • 如何装配
    • 主流程
    • 解析配置类
    • 加载配置类配置的beanDefinition
  • 总结

何时装配

beanFactoryPostProcessor的执行入口

实际上@Bean、@ComponentScan、@Import配置的bean装配逻辑是在ConfigurationClassPostProcessor实现的。这个类实现了BeanDefinitionRegistryPostProcessor接口,且又因为该接口继承自BeanFactoryPostProcessor,所以ConfigurationClassPostProcessor就是一个BeanFactoryPostProcessor。

BeanDefinitionRegistryPostProcessor 提供了一个回调方法 postProcessBeanDefinitionRegistry(),可以在这个方法中对 BeanDefinition 进行修改或者添加新的 BeanDefinition。

单从装配上来说,把ConfigurationClassPostProcessor认为是BeanDefinitionRegistryPostProcessor会比BeanFactoryPostProcessor更贴切。虽然BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor,但是顾名思义BeanDefinitionRegistryPostProcessor在BeanFactoryPostProcessor基础上增加了BeanDefinitionRegistry的功能。

从这一点入手即可知道@Bean、@ComponentScan、@Import配置的bean就是在执行所有的BeanFactoryPostProcessor这一步骤装配的,调用流程如下。
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配_第1张图片

在实际执行BeanFactoryPostProcessor时,spring容器将具体实现委托给了PostProcessorRegistrationDelegate这个工具类。PostProcessorRegistrationDelegate代码中处理BeanFactoryPostProcessord的代码如下

PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

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

		Set<String> processedBeans = new HashSet<>();

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

			//----------遍历spring容器当前已有的beanFactoryPostProcessors---------//
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				}
				else {
					regularPostProcessors.add(postProcessor);
				}
			}

			//-----------执行已注册的 BeanDefinitionRegistryPostProcessor bean--------------//
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			//postProcessBeanDefinitionRegistry()方法

			//首先先执行实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
			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, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			//然后执行实现了Ordered接口的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, beanFactory.getApplicationStartup());
			currentRegistryProcessors.clear();

			//最后执行其他未被扫描到的BeanDefinitionRegistryPostProcessor
			//	因为处理的过程中可能会注册新的BeanDefinitionRegistryPostProcessor
			//	所以这里用循环确保所有的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, beanFactory.getApplicationStartup());
				currentRegistryProcessors.clear();
			}

			// postProcessBeanFactory()方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			//没有实现BeanDefinitionRegistry接口则直接执行执行BeanFactoryPostProcessor
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		//--------------------------执行已注册的 BeanFactoryPostProcessor bean------------------------------//
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// 跟上面一样
		// 都是先按 实现了PriorityOrdered接口、实现了Ordered接口、其他 的顺序处理 BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// 跳过已经执行的BeanFactoryPostProcessor
			}
			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);
			}
		}

		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		beanFactory.clearMetadataCache();
	}

这个方法首先会判断beanFactory是否来自BeanDefinitionRegistry,如果不是则直接执行beanFactory.beanFactoryPostProcessors属性指向的容器本身已有的BeanFactoryPostProcessors,如果是则保证先执行所有的BeanDefinitionRegistryPostProcessor(包括BeanDefinition中注册的)后再执行BeanFactoryPostProcessors(包括BeanDefinition中注册的)。两者的执行都按 本身已有的->BeanDefinition中PriorityOrdered修饰的->BeanDefinition中Ordered修饰的->BeanDefinition中其他未被执行的顺序执行

ConfigurationClassPostProcessor的注册

上面展示了spring容器在启动的过程中是如何执行BeanFactoryPostProcessors的。那么问题来了,ConfigurationClassPostProcessor这个BeanFactoryPostProcessors是spring容器自带的还是BeanDefinition中注册的呢?如果是注册的,那是何时注册的呢?
我们首先排除容器自带的,通过debug代码可以发现当执行invokeBeanFactoryPostProcessors方法时,spring容器自带的BeanFactoryPostProcessors即传进来的beanFactoryPostProcessors参数为空。
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配_第2张图片
既然不是自带的BeanFactoryPostProcessors那就肯定在前面的某一步中,注册了ConfigurationClassPostProcessor这么一个BeanDefinition。
通过debug代码分析可以得知,在执行refresh方法前(甚至在register方法执行前)就已经存在beanName为org.springframework.context.annotation.internalConfigurationAnnotationProcessor的ConfigurationClassPostProcessor bean了。由此可以推断是在AnnotationConfigApplicationContext容器初始化的时候注册的。
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配_第3张图片
查看初始化流程,可以发现创建reader时会执行AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配_第4张图片
AnnotationConfigUtils.registerAnnotationConfigProcessors中会默认注册一些beanDefinition,ConfigurationClassPostProcessor就是在这里注册的
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配_第5张图片


如何装配

主流程

接下来看ConfigurationClassPostProcessor的具体注册beanDefinition的逻辑
ConfigurationClassPostProcessor#registerAnnotationConfigProcessors

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		String[] candidateNames = registry.getBeanDefinitionNames();

		// 遍历 BeanDefinition 找到所有的 Configuration 配置类
		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			// 如果CONFIGURATION_CLASS_ATTRIBUTE属性不为空说明已经处理过了,打印日志
			if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
				if (logger.isDebugEnabled()) {
					logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
				}
			}
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// 没有配置类直接返回
		if (configCandidates.isEmpty()) {
			return;
		}

		// 配置类按order注解排序
		configCandidates.sort((bd1, bd2) -> {
			int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
			int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
			return Integer.compare(i1, i2);
		});

		// beanName生成器
		SingletonBeanRegistry sbr = null;
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
				if (generator != null) {
					this.componentScanBeanNameGenerator = generator;
					this.importBeanNameGenerator = generator;
				}
			}
		}

		// 环境变量
		if (this.environment == null) {
			this.environment = new StandardEnvironment();
		}

		// 解析 @Configuration class 并注册解析到的bean
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
		Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
		do {
			StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
			// 解析Configuration配置类
			parser.parse(candidates);
			parser.validate();

			Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
			configClasses.removeAll(alreadyParsed);

			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			// 注册configurationClass 配置的bean
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);
			processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

			// 找出新注册的BeanDefinition再次进入循环
			candidates.clear();
			if (registry.getBeanDefinitionCount() > candidateNames.length) {
				String[] newCandidateNames = registry.getBeanDefinitionNames();
				Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
				Set<String> alreadyParsedClasses = new HashSet<>();
				for (ConfigurationClass configurationClass : alreadyParsed) {
					alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
				}
				for (String candidateName : newCandidateNames) {
					if (!oldCandidateNames.contains(candidateName)) {
						BeanDefinition bd = registry.getBeanDefinition(candidateName);
						if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
								!alreadyParsedClasses.contains(bd.getBeanClassName())) {
							candidates.add(new BeanDefinitionHolder(bd, candidateName));
						}
					}
				}
				candidateNames = newCandidateNames;
			}
		}
		while (!candidates.isEmpty());

		if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
			sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
		}

		if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
			((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
		}
	}

说通俗一点就是
1:找到所有配置类
2:解析配置类
3:加载配置类配置的beanDefinition
4:循环23直至没有新的配置类加载

解析配置类

点进去parser.parse(candidates)
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配_第6张图片
最终会来到ConfigurationClassParser#doProcessConfigurationClass

protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {

		if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
			// 解析成员类
			processMemberClasses(configClass, sourceClass, filter);
		}

		// 解析 @PropertySource 注解
		for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), PropertySources.class,
				org.springframework.context.annotation.PropertySource.class)) {
			if (this.environment instanceof ConfigurableEnvironment) {
				processPropertySource(propertySource);
			}
			else {
				logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
						"]. Reason: Environment must implement ConfigurableEnvironment");
			}
		}

		// 解析 @ComponentScan 注解
		Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
				sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
		if (!componentScans.isEmpty() &&
				!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
			for (AnnotationAttributes componentScan : componentScans) {
				//最终会调用ClassPathBeanDefinitionScanner.doScan()方法实现beanDefinition的注册
				Set<BeanDefinitionHolder> scannedBeanDefinitions =
						this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
				for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
					BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
					if (bdCand == null) {
						bdCand = holder.getBeanDefinition();
					}
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
						parse(bdCand.getBeanClassName(), holder.getBeanName());
					}
				}
			}
		}

		// 解析 @Import 注解
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

		// 解析 @ImportResource 注解
		AnnotationAttributes importResource =
				AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
		if (importResource != null) {
			String[] resources = importResource.getStringArray("locations");
			Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
			for (String resource : resources) {
				String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
				configClass.addImportedResource(resolvedResource, readerClass);
			}
		}

		// 解析 @Bean 注解(与@Component不同的是这里不会立即注册到beanDefinitionMap中,是在后续的loadBeanDefinition方法才注册)
		Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
		for (MethodMetadata methodMetadata : beanMethods) {
			configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
		}

		// 递归接口的默认实现
		processInterfaces(configClass, sourceClass);

		// 递归父类
		if (sourceClass.getMetadata().hasSuperClass()) {
			String superclass = sourceClass.getMetadata().getSuperClassName();
			if (superclass != null && !superclass.startsWith("java") &&
					!this.knownSuperclasses.containsKey(superclass)) {
				this.knownSuperclasses.put(superclass, configClass);
				return sourceClass.getSuperClass();
			}
		}

		return null;
	}

在这一步会解析配置类的 成员类、@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean 以及递归接口默认实现和递归父类,将解析到的结果封装成ConfigurationClass保存到parse.configurationClasses属性,然后再调用reader.loadBeanDefinitions(configClasses)方法实现beanDefintion的加载。

需要注意的是@ComponentScan会在解析这一步的时先将对应的beanDefinition注册到map中了,而@Import、@Bean注解的beanDefinition是在后续的loadBeanDefinitions才注册到map中的。

加载配置类配置的beanDefinition

ConfigurationClassBeanDefinitionReader#loadBeanDefinitions
spring5源码篇(4)——beanFactoryPostProcessor执行/注解bean的装配_第7张图片
可以看到,@Import和@Bean配置的bean都在这一步注册了。

上图提到了两次@Import注解,但作用是不一样的。第一次如果这个类是被Import进来的则先注册他自身,第二次是注册他Import过来类。不过这一步最主要也是最常用的还是注册了@Bean注解的bean。

总结

在启动AnnotationConfigApplicationContext容器创建reader时会默认注册一些beanDefinition,其中就包括ConfigurationClassPostProcessor。ConfigurationClassPostProcessor又是一个beanFactoryPostProcessor,所以后续refresh中invokeBeanFactoryPostProcessors方法执行所有BeanFactoryPostProcessor的方法时就会调用ConfigurationClassPostProcessor的相关逻辑实现@Bean、@ComponentScan、@Import配置的bean的装配。
实现大致如下
1:找到所有配置类
2:解析配置类(@ComponentScan在这一步注册)
3:加载配置类配置的beanDefinition(@Import,@Bean在这一步注册)
4:循环23直至没有新的配置类加载
最后的最后
@ComponentScan调用ClassPathBeanDefinitionScanner.doScan()
@Bean调用BeanDefinitionRegistry.registerBeanDefinition()
@Import调用ImportBeanDefinitionRegistrar.registerBeanDefinitions()
实现beanDefinition的注册。

你可能感兴趣的:(Spring,spring,java)