Spring扫描

39

最近在学习Spring源码,但是我现在不太想把自己的整个学习笔记贴出来,还是要精炼,学习笔记几千上万字不太利于读者阅读

spring的版本是当时的最新版6.1.x

抽取其中觉得有必要分享的点写一篇博客记录一下,顺便总结提炼.这篇博客内容主要介绍的是spring中invokeBeanFactoryPostProcessors方法和ConfigurationClassPostProcessor类的代码的执行,是比较简单的部分

会使用到的接口

提前说明一下涉及到的接口

BeanFactoryPostProcessor

这里就要先说一下spring内部的各种PostProcessor,我们最常用的就是BeanPostProcessor,他是spring构建Bean时的后置处理器.然而BeanFactoryPostProcessor,是spring构建BeanFactory的后置处理器

spring首先构建BeanFactory,所以BeanFactoryPostProcessor的生命周期在BeanPostProcessor之前

源码会涉及到的2个接口,分别是:

  • BeanFactoryPostProcessor,继承该接口需要实现postProcessBeanFactory

  • BeanDefinitionRegistryPostProcessor,是BeanFactoryPostProcessor的子接口,需要实现postProcessBeanDefinitionRegistry,可以调用该接口创建BeanDefinition

@Component
public class MengnanBeanFactoryPostProcessor
		// implements BeanFactoryPostProcessor {
		// (BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)
		implements BeanDefinitionRegistryPostProcessor {
	@Override
	// 可以通过该方法注册BeanDefinition
	// 先执行
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
		beanDefinition.setBeanClassName("info.mengnan.User");
		beanDefinition.setLazyInit(false);
		registry.registerBeanDefinition("user", beanDefinition);
	}

	@Override
	// 能拿到BeanDefinition但是不能注册BeanDefinition
	// 可以调用BeanFactory的接口
	// 后执行
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		beanFactory.registerSingleton("member", new MemberService());

		// 一般只能拿到BeanDefinition
		// 因为BeanFactoryPostProcessor的在spring生命周期时还没有创建Bean
		// 可以看refresh方法的invokeBeanFactoryPostProcessors
		// 要最后才会执行finishBeanFactoryInitialization
		BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService");

	}
}

Ordered

同样也会涉及到2个接口

  • Ordered,需要实现getOrder方法

  • PriorityOrdered,Ordered的子接口,也需要实现getOrder方法

都和Bean执行顺序有关,不过PriorityOrdered的优先级大于Ordered,在以下源码中也有体现

ImportSelector

执行ConfigurationClassPostProcessor会调用的接口,会将数组内的类进行导入为配置类

@Component
public class MengnanImportSelector implements ImportSelector {
	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		return new String[]{MemberService.class.getName()};
	}
}

正文

如果你学习了Spring,你也就必然知道Spring的使用方式

// 传递一个类,一般情况下是配置类
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);

在其中会执行refresh方法,spring的扫描注册等操作都放在其中

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
	// 注册reader和scanner
	this();
	// 注册配置类
	register(componentClasses);
	refresh();
}

执行refresh方法,其中会执行invokeBeanFactoryPostProcessors

因为代码太长我就直接截图了

这里我备注一下这篇博文的重点是invokeBeanFactoryPostProcessors,不过内部执行逻辑和下面的registerBeanPostProcessors方法极为类似

最终内部会执行

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	// 此时getBeanFactoryPostProcessors()只能拿到执行refresh方法之前存储的BeanFactoryPostProcessor
	// 重点方法
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
}

在此处debug会发现getBeanFactoryPostProcessors返回的是一个空数组,因为spring还没有开始扫描,除非你使用以下特殊方式

// 使用无参构造后手动refresh
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.addBeanFactoryPostProcessor(new MengnanBeanFactoryPostProcessor());
context.refresh();

invokeBeanFactoryPostProcessors主要做的就是扫描、不断注册、创建、排序BeanFactoryPostProcessors,注册BeanDefinition

构造BeanFactoryPostProcessor

源码很长,但是仔细阅读发现并不复杂,以下代码可以分为3个部分,以下内容建议对照源码阅读

外部传入创建

通过方法参数传递进来的BeanFactoryPostProcessor,默认情况下是空数组,也就是说如果你不使用上述的特殊方式,这段代码永远不会执行

这里的代码和之后的代码有显著区别,会立刻执行postProcessBeanDefinitionRegistry方法,不过postProcessBeanFactory却会存储起来之后执行

这里声明了一个名为processedBeans的Set集合,processedBeans的作用是存储所有处理过的PostProcessor,防止重复执行

但是有一块疑点,通过我前面说的特殊方式传入的PostProcessor不会存入processedBeans,所以会导致重复执行.不知道为什么spring要这么设计

外部传入的postProcessBeanDefinitionRegistry优先级最高

  • 执行通过外部传入的BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry方法

// 存储的是执行过的Bean
Set<String> processedBeans = new HashSet<>();

if (beanFactory instanceof BeanDefinitionRegistry registry) {
	List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
	List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
	// 先处理外部传递的beanFactoryPostProcessors
	// beanFactoryPostProcessors一般情况下都是空数组的,除非在手动refresh之前执行了addBeanFactoryPostProcessor方法
	for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
		// 对于BeanDefinitionRegistryPostProcessor对象,会执行postProcessBeanDefinitionRegistry
		// 执行全部的postProcessBeanDefinitionRegistry方法
		if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
			registryProcessor.postProcessBeanDefinitionRegistry(registry);
			registryProcessors.add(registryProcessor);
		}
		else {
			// BeanFactoryPostProcessor的生命周期比较靠后,所以此处没有直接执行postProcessBeanFactory
			regularPostProcessors.add(postProcessor);
		}
	}

BeanDefinitionRegistryPostProcessor

不断调用getBeanNamesForType,获取postProcessorNames,为什么要不断获取呢,因为调用beanDefinitionRegistryPostProcessor会创建新的BeanDefinition,所以要不断获取直到获取不到为止

第一次获取时postProcessorNames中一般情况只有一个元素:org.springframework.context.annotation.internalConfigurationAnnotationProcessor ,这个类非常重要,它就是ConfigurationClassPostProcessor

我这里说的一般情况指的是使用AnnotationConfigApplicationContext(Class<?>... componentClasses)这个构造方法来创建spring

ConfigurationClassPostProcessor这个类在spring构造方法中创建AnnotatedBeanDefinitionReader时就已经注册为BeanDefinition

通过代码可以看到有以下生命周期进行执行,整理一下发现代码本身并不复杂,只是spring设置了非常复杂的生命周期

  • 执行继承了BeanDefinitionRegistryPostProcessor和PriorityOrdered的postProcessBeanDefinitionRegistry方法

  • 执行继承了BeanDefinitionRegistryPostProcessor和Ordered的postProcessBeanDefinitionRegistry方法

  • 执行其他的BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry方法

  • 执行目前方法内获取的所有BeanDefinitionRegistryPostProcessorprocessBeanFactory方法

  • 执行通过外部传入的BeanDefinitionRegistryPostProcessorprocessBeanFactory方法

每次执行过后都会存储到processedBeans中

// 当此循环的RegistryProcessors
// 以下会经过多次循环,每次循环都会将RegistryPostProcessor暂时放入
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// 没有开始扫描所以依然拿不到自己定义的PostProcessor
// (除非创建AnnotationConfigApplicationContext传了包名则会调用scan方法提前扫描)
// 但是可以拿到提前放入的PostProcessor的BeanDefinition
// 此处可以拿到ConfigurationClassPostProcessor(在refresh之前就已经放入了)
// ConfigurationClassPostProcessor的主要作用就是扫描
String[] postProcessorNames =
		beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
	// 判断是否实现了PriorityOrdered接口
	if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
		// 获取ConfigurationClassPostProcessor的BeanDefinition并创建为Bean
		currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
		processedBeans.add(ppName);
	}
}
// 排序@Ordered指定的数字进行排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行所有的RegistryProcessors的postProcessBeanDefinitionRegistry
// 解析配置了,执行扫描操作(如有ComponentScan)
// 特别是ConfigurationClassPostProcessor
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

// 再一次拿到所有的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();

boolean reiterate = true;
while (reiterate) {
	reiterate = false;
	// 因为RegistryPostProcessor会产生新的RegistryPostProcessor,所以要不断循环,直到拿不到新的为止
	postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
	for (String ppName : postProcessorNames) {
		// 所有postProcessorNames都存储在processedBeans中,reiterate为false,退出while循环
		if (!processedBeans.contains(ppName)) {
			currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
			processedBeans.add(ppName);
			// 拿到新的设置为true继续while循环
			reiterate = true;
		}
	}
	sortPostProcessors(currentRegistryProcessors, beanFactory);
	registryProcessors.addAll(currentRegistryProcessors);
	invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup(
	currentRegistryProcessors.clear();
}

// 执行完成所有postProcessBeanDefinitionRegistry后开始执行postProcessBeanFactory
// 此处也有先后顺序,先执行直接实现子接口(BeanDefinitionRegistryPostProcessor)的
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 最后执行手动添加的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

BeanFactoryPostProcessor

以下代码变的简单,因为BeanFactoryPostProcessor无法生产BeanDefinition所以只需要一次循环分类PriorityOrdered、Ordered,排序后依次执行,最后再执行剩余的BeanFactoryPostProcessor

此处代码也包含以下生命周期

  • 执行继承了BeanFactoryPostProcessor和PriorityOrdered的processBeanFactory方法

  • 执行继承了BeanFactoryPostProcessor和Ordered的processBeanFactory方法

  • 执行其他的BeanFactoryPostProcessorprocessBeanFactory方法

// 代码执行到这里就把所有的BeanDefinitionRegistryPostProcessor执行完了,这就说明不会产生新的BeanDefinition了
// 现开始获取BeanFactoryPostProcessor
String[] postProcessorNames =
		beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 因为不会产生新的BeanDefinition
// 所以实现变得更简单,执行逻辑和BeanDefinitionRegistryPostProcessor一样
for (String ppName : postProcessorNames) {
	if (processedBeans.contains(ppName)) {
		// 跳过
	}
	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);
// 执行postProcessBeanFactory
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();

ConfigurationClassPostProcessor

开始解析配置类

会执行2步,会先注册BeanDefinition,之后才会执行postProcessBeanFactory

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
	int registryId = System.identityHashCode(registry);
	if (this.registriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
	}
	if (this.factoriesPostProcessed.contains(registryId)) {
		throw new IllegalStateException(
				"postProcessBeanFactory already called on this post-processor against " + registry);
	}
	this.registriesPostProcessed.add(registryId);
	// 解析配置类
	// 扫描得到BeanDefinition
	processConfigBeanDefinitions(registry);
}

配置类的定义

这里先要知道什么是配置类,我们可以在ConfigurationClassUtils.checkConfigurationClassCandidate看到spring对于配置类中的明确定义

static boolean checkConfigurationClassCandidate(
		BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
	String className = beanDef.getBeanClassName();
	if (className == null || beanDef.getFactoryMethodName() != null) {
		return false;
	}
	// 拿到该BeanDefinition对应的注解元信息
	AnnotationMetadata metadata;
	if (beanDef instanceof AnnotatedBeanDefinition annotatedBd &&
			className.equals(annotatedBd.getMetadata().getClassName())) {

		metadata = annotatedBd.getMetadata();
	}
	else if (beanDef instanceof AbstractBeanDefinition abstractBd && abstractBd.hasBeanClass()) {

		Class<?> beanClass = abstractBd.getBeanClass();
		if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
				BeanPostProcessor.class.isAssignableFrom(beanClass) ||
				AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
				EventListenerFactory.class.isAssignableFrom(beanClass)) {
			return false;
		}
		metadata = AnnotationMetadata.introspect(beanClass);
	}
	else {
		try {
			MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
			metadata = metadataReader.getAnnotationMetadata();
		}
		catch (IOException ex) {
			if (logger.isDebugEnabled()) {
				logger.debug("Could not find class file for introspecting configuration annotations: " +
						className, ex);
			}
			return false;
		}
	}
	// 判断是否有@Configuration
	Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
	// 如果加了@Configuration并且proxyBeanMethods设置为不为false(默认是true)
	if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
		// FULL配置类
		beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
	}
	// 加了@Configuration
	else if (config != null || Boolean.TRUE.equals(beanDef.getAttribute(CANDIDATE_ATTRIBUTE)) ||
			isConfigurationCandidate(metadata)) {
		// LITE配置类
		beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
	}
	else {
		return false;
	}
	Integer order = getOrder(metadata);
	if (order != null) {
		beanDef.setAttribute(ORDER_ATTRIBUTE, order);
	}
	return true;
}

我们可以看到spring将配置类分为FULL配置类和LITE配置类

  • 类上添加了@Configuration并且proxyBeanMethods为true为FULL配置类

  • 类上添加了@Configuration并且proxyBeanMethods为false,或者isConfigurationCandidate方法执行为true则为LITE配置类

static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
		// 配置类不能是接口
		if (metadata.isInterface()) {
			return false;
		}
		// 配置类只要包含@Component、@ComponentScan、@Import、@ImportResource中的一个
		for (String indicator : candidateIndicators) {
			if (metadata.isAnnotated(indicator)) {
				return true;
			}
		}
		// 或者有加了@Bean的方法
		return hasBeanMethods(metadata);
	}

两者的区别,如果是FULL配置类,spring会基于这个类创建代理类

有兴趣的可以参照ConfigurationClassEnhancer的intercept方法

@Configuration(proxyBeanMethods = true)
public class AppConfig {

	@Bean
	public MemberService memberService() {
		return new MemberService();
	}

	@Bean
	// 如果proxyBeanMethods为true,2个memberService执行结果一致
	// 内部执行的时候会去getBean,所以返回的都是同一个对象
	public UserService userService() {
		System.out.println(memberService()); 
		System.out.println(memberService());
		return new UserService();
	}
}

解析配置类

让我们具体看一下ConfigurationClassPostProcessor到底干了什么

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
	List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
	// 拿到目前为止所有的BeanDefinition字符串数组
	String[] candidateNames = registry.getBeanDefinitionNames();
	for (String beanName : candidateNames) {
		BeanDefinition beanDef = registry.getBeanDefinition(beanName);
		// 如果已经做了配置类处理,忽略
		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);
	});

	SingletonBeanRegistry singletonRegistry = null;
	if (registry instanceof SingletonBeanRegistry sbr) {
		singletonRegistry = sbr;
		if (!this.localBeanNameGeneratorSet) {
			BeanNameGenerator generator = (BeanNameGenerator) singletonRegistry.getSingleton(
					AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
			// 设置Bean名称的生成器
			if (generator != null) {
				this.componentScanBeanNameGenerator = generator;
				this.importBeanNameGenerator = generator;
			}
		}
	}
	if (this.environment == null) {
		this.environment = new StandardEnvironment();

	// 生成配置类的解析器
	ConfigurationClassParser parser = new ConfigurationClassParser(
			this.metadataReaderFactory, this.problemReporter, this.environment,
			this.resourceLoader, this.componentScanBeanNameGenerator, registry);
	Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
	Set<ConfigurationClass> alreadyParsed = CollectionUtils.newHashSet(configCandidates.size());
	// 解析配置类,可能通过一个配置类得到多个配置类
	do {
		StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
		// 进行解析配置类,并收集deferredImportSelectorHandler
		// 最后解析完所有配置类后执行deferredImportSelectorHandler中的延迟处理的配置
		// 参照 [开始解析]
		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());
		}
		// 把所有配置类解析为BeanDefinition,具体参见下面[loadBeanDefinitionsForConfigurationClass的方法说明]
		this.reader.loadBeanDefinitions(configClasses);
		alreadyParsed.addAll(configClasses);
		processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();
		candidates.clear();
		// 如果BeanDefinition增加了,说明增加了配置类
		if (registry.getBeanDefinitionCount() > candidateNames.length) {
			String[] newCandidateNames = registry.getBeanDefinitionNames();
			Set<String> oldCandidateNames = Set.of(candidateNames);
			Set<String> alreadyParsedClasses = CollectionUtils.newHashSet(alreadyParsed.size());
			for (ConfigurationClass configurationClass : alreadyParsed) {
				alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
			}
			for (String candidateName : newCandidateNames) {
				if (!oldCandidateNames.contains(candidateName)) {
					BeanDefinition bd = registry.getBeanDefinition(candidateName);
					// 检查多出来的BeanDefinition是否是配置类,需不需要解析
					if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
							!alreadyParsedClasses.contains(bd.getBeanClassName())) {
						candidates.add(new BeanDefinitionHolder(bd, candidateName));
					}
				}
			}
			candidateNames = newCandidateNames;
		}
	}
	while (!candidates.isEmpty());
	if (singletonRegistry != null && !singletonRegistry.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
		singletonRegistry.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
	}
	this.propertySourceDescriptors = parser.getPropertySourceDescriptors();
	if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {
		cachingMetadataReaderFactory.clearCache();
	}
}

spring会解析3种注解@Import、@Bean、@ImportResource

这里分别介绍一下这3个注解的区别

  • @Import 将内部的类解析出来进行处理

  • @Bean 执行被@Bean标注的方法,拿到它的返回值

  • @ImportResource 处理xml文件中的Bean对象

private void loadBeanDefinitionsForConfigurationClass(
		ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
	if (trackedConditionEvaluator.shouldSkip(configClass)) {
		String beanName = configClass.getBeanName();
		if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
			this.registry.removeBeanDefinition(beanName);
		}
		this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
		return;
	}
	// 处理@Import的类并将它转换为BeanDefinition
	if (configClass.isImported()) {
		registerBeanDefinitionForImportedConfigurationClass(configClass);
	}
	// 处理@Bean并生成BeanDefinition
	for (BeanMethod beanMethod : configClass.getBeanMethods()) {
		loadBeanDefinitionsForBeanMethod(beanMethod);
	}
	// 处理@ImportResource并生成BeanDefinition
	loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
	// 处理@Import中的ImportBeanDefinitionResister的registerBeanDefinitions生成的BeanDefinition
	loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

开始解析

public void parse(Set<BeanDefinitionHolder> configCandidates) {
	for (BeanDefinitionHolder holder : configCandidates) {
		BeanDefinition bd = holder.getBeanDefinition();
		try {
			// 将不同类型的BeanDefinition进行封装后执行同一个parse方法
			if (bd instanceof AnnotatedBeanDefinition annotatedBeanDef) {
				parse(annotatedBeanDef, holder.getBeanName());
			}
			else if (bd instanceof AbstractBeanDefinition abstractBeanDef && abstractBeanDef.hasBeanClass()) {
				parse(abstractBeanDef.getBeanClass(), holder.getBeanName());
			}
			else {
				parse(bd.getBeanClassName(), holder.getBeanName());
			}
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(
					"Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
		}
	}
	// 循环执行parse结束后
	// 处理deferredImportSelectors
	// 当批所有配置解析完了以后才会执行(spring解析配置可以理解为是一批批执行的)
	// deferredImportSelectors表示推迟处理的ImportSelector
	this.deferredImportSelectorHandler.process();
}

private void parse(AnnotatedBeanDefinition beanDef, String beanName) {
	processConfigurationClass(
			new ConfigurationClass(beanDef.getMetadata(), beanName, (beanDef instanceof ScannedGenericBeanDefinition)),
			DEFAULT_EXCLUSION_FILTER);
}

解析好配置类后会将结果存储在configurationClasses这个map中

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) {
	// 看看是否符合@Condition注解的条件
	if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
		return;
	}
	ConfigurationClass existingClass = this.configurationClasses.get(configClass);
	if (existingClass != null) {
		// 2个类同时@Import了同一个配置类,将该配置合并
		if (configClass.isImported()) {
			if (existingClass.isImported()) {
				existingClass.mergeImportedBy(configClass);
			}
			return;
		}
		else if (configClass.isScanned()) {
			String beanName = configClass.getBeanName();
			if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
				this.registry.removeBeanDefinition(beanName);
			}
			return;
		}
		else {
			this.configurationClasses.remove(configClass);
			removeKnownSuperclass(configClass.getMetadata().getClassName(), false);
		}
	}

	SourceClass sourceClass = null;
	try {
		sourceClass = asSourceClass(configClass, filter);
		do {
			// 开始真正解析配置类
			sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
		}
		while (sourceClass != null);
	}
	catch (IOException ex) {
		throw new BeanDefinitionStoreException(
				"I/O failure while processing configuration class [" + sourceClass + "]", ex);
	}
	// 解析好的配置信息存储到configurationClasses,稍后会使用
	this.configurationClasses.put(configClass, configClass);
}

开始真正解析配置类

并处理不同类型的注解,将内部的类转换为ConfigurationClass

  • 类上存在@Component,则递归执行解析它的内部类

  • 类上存在@PropertySource添加到PropertySourceProcessor的environment中

  • 类上存在@ComponentScan,进行扫描(内部最终会执行doScan方法)并获取一系列BeanDefinition,如果是配置类则继续解析

  • 类上存在@Import,这个比较复杂后续说明

  • 类上存在@ImportResource,会将资源路径中的xml文件存储到importedResources中

  • 方法上存在@Bean,会将这个方法封装为BeanMethod对象并存储在beanMethods中

  • 如果配置类存在父类,还会对父类进行解析

protected final SourceClass doProcessConfigurationClass(
		ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
		throws IOException {
	// 是否包含@Component
	if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
		// 获取所有内部类
		processMemberClasses(configClass, sourceClass, filter);
	}
	// 判断是否包含@PropertySource
	// Process any @PropertySource annotations
	for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), org.springframework.context.annotation.PropertySource.class,
			PropertySources.class, true)) {
		if (this.propertySourceRegistry != null) {
			this.propertySourceRegistry.processPropertySource(propertySource);
		}
		else {
			logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
					"]. Reason: Environment must implement ConfigurableEnvironment");
		}
	}
	// 判断是否包含@ComponentScan
	// 如果包含该注解,就会触发扫描操作
	// Search for locally declared @ComponentScan annotations first.
	Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
			sourceClass.getMetadata(), ComponentScan.class, ComponentScans.class,
			MergedAnnotation::isDirectlyPresent);
	// Fall back to searching for @ComponentScan meta-annotations (which indirectly
	// includes locally declared compnmosed annotations).
	if (componentScans.isEmpty()) {
		componentScans = AnnotationConfigUtils.attributesForRepeatable(sourceClass.getMetadata(),
				ComponentScan.class, ComponentScans.class, MergedAnnotation::isMetaPresent);
	}
	if (!componentScans.isEmpty()) {
		List<Condition> registerBeanConditions = collectRegisterBeanConditions(configClass);
		if (!registerBeanConditions.isEmpty()) {
			throw new ApplicationContextException(
					"Component scan for configuration class [%s] could not be used with conditions in REGISTER_BEAN phase: %s".formatted(configClass.getMetadata().getClassName(), registerBeanConditions));
		}
		for (AnnotationAttributes componentScan : componentScans) {
			// 扫描得到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();
				}
				// 检查扫描出来的BeanDefinition是不是配置类
				if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
					// 如果是解析(递归)
					parse(bdCand.getBeanClassName(), holder.getBeanName());
				}
			}
		}
	}
	// 处理@Import
	processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
	// 处理@ImportResource,将xml文件路径添加到importedResources中
	// @ImportResource("spring.xml")
	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方法(暂时只是找出来并未处理),添加到beanMethods属性中
	// 例如配置类实现了default修饰的方法上添加了@Bean
	Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
	for (MethodMetadata methodMetadata : beanMethods) {
		if (methodMetadata.isAnnotated("kotlin.jvm.JvmStatic") && !methodMetadata.isStatic()) {
			continue;
		}
		configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
	}
	// 将BeanMethod封装到beanMethods中
	processInterfaces(configClass, sourceClass);

	// 解析父类
	if (sourceClass.getMetadata().hasSuperClass()) {
		String superclass = sourceClass.getMetadata().getSuperClassName();
		if (superclass != null && !superclass.startsWith("java")) {
			boolean superclassKnown = this.knownSuperclasses.containsKey(superclass);
			this.knownSuperclasses.add(superclass, configClass);
			if (!superclassKnown) {
				return sourceClass.getSuperClass();
			}
		}
	}
	return null;
}

@Import

如果配置类存在@Import

  • 如果导入的类只是普通的类就执行常规的导入

  • 如果导入的类实现了ImportSelector,实例化

    • 如果是普通ImportSelector,直接调用selectImports需要返回一个数组进行批量导入,然后把这些类调用processImports(不断递归执行,直到解析的类全部都是普通的配置类为止)

    • 如果是DeferredImportSelector,暂存在deferredImportSelectors,最后在processConfigBeanDefinitions方法循环中解析完当前批的配置最后才解析存储在这个list里的配置

  • 如果导入的类实现了ImportBeanDefinitionRegistrar,实例化并将该类存储到importBeanDefinitionRegistrars中(实现ImportBeanDefinitionRegistrar也可以创建BeanDefinition,但是这里并没有直接调用registerBeanDefinitions)

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
		Collection<SourceClass> importCandidates, Predicate<String> filter, boolean checkForCircularImpor
	if (importCandidates.isEmpty()) {
		return;
	}
	// 循环导入会导致异常
	if (checkForCircularImports && isChainedImportOnStack(configClass)) {
		this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
	}
	else {
		this.importStack.push(configClass);
		try {
			for (SourceClass candidate : importCandidates) {
				// 通过@Import导入的类是否包含ImportSelector
				if (candidate.isAssignable(ImportSelector.class)) {
					Class<?> candidateClass = candidate.loadClass();
					// 实例化并且转换为ImportSelector
					ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, Import
							this.environment, this.resourceLoader, this.registry);
					Predicate<String> selectorFilter = selector.getExclusionFilter();
					if (selectorFilter != null) {
						filter = filter.or(selectorFilter);
					}
					if (selector instanceof DeferredImportSelector deferredImportSelector) {
						// 如果import的是DeferredImportSelector
						// 将DeferredImportSelector类型的临时存储到deferredImportSelectors
						this.deferredImportSelectorHandler.handle(configClass, deferredImportSelector);
					}
					else {
						// 解析selectImports方法,并且递归执行
						String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata
						Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, f
						processImports(configClass, currentSourceClass, importSourceClasses, filter, fals
					}
				}
				// 通过@Import导入的类是否包含ImportBeanDefinitionRegistrar
				// ImportBeanDefinitionRegistrar也可以注册BeanDefinition
				else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
					Class<?> candidateClass = candidate.loadClass();
					ImportBeanDefinitionRegistrar registrar =
							ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegi
									this.environment, this.resourceLoader, this.registry);
					// 并没有直接调用registerBeanDefinitions而是存储到importBeanDefinitionRegistrars
					configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadat
				}
				// 是否没加上以上2个接口
				else {
					// 直接把该类当作配置类
					this.importStack.registerImport(
							currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
					processConfigurationClass(candidate.asConfigClass(configClass), filter);
				}
			}
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(
					"Failed to process import candidates for configuration class [" +
					configClass.getMetadata().getClassName() + "]: " + ex.getMessage(), ex);
		}
		finally {
			this.importStack.pop();
		}
	}
}

总结

Spring的生命周期中会执行BeanFactoryPostProcessor,它会对BeanFactory进行加工.我们可以实现BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口来实现这个功能.拿到BeanFactory并对BeanDefinition进行创建或修改.因为是在创建Bean实例之前,所以对BeanDefinition的修改是会生效的

其中就包含最重要的ConfigurationClassPostProcessor,它也是spring中第一个被创建的BeanDefinition.获取类上的注解,并判断是否是配置类,如果包含@ComponentScan还会进行doScan操作

最终将以下信息封装为ConfigurationClass对象,最后存储在存储在configurationClasses中

  • 如果包含@Bean会把方法封装到beanMethods属性中

  • 如果包含@ImportResource会将资源路径存储在importedResources属性中

  • 如果包含@Import会将内部的类加载为配置类

  • 如果包含@Component,会解析它的内部类是否为配置类