第五节 Starter 的加载全貌

tips:下载源码,再结合本章内容,学习整个加载过程。

上一章,我们理解了 spring.factories 的触发时机,但放在 SpringBoot 的整个加载过程来讲,只能算部分。 而这一章,将从 SpringBoot 的加载全貌,进一步理解 Starter 的加载时机。

SpringBoot 的整个启动流程是比较复杂的,代码也较多;尽量抓住核心部分进行讲解。当然也不能对所有代码逐行进行分析, 坚持二八原则。

一、SpringBoot 启动过程

对于整个 SpringBoot 应用组成,可以分为两个部分。 一部分是 SpringBoot 核心基础,另外一部分是 spring framework 框架核心。通过这两部分组合,实现 SpringBoot 的加载启动

下图展示了 SpringBoot 启动过程高层次的组件图。 本文主要围绕图片中左边部分(SpringBoot加载过程)

二、 解析关键类

Spring Boot 启动的关键代表类。 ConfigurationClassParser 在整个 bean 启动过程中起到了十分关键的作用,它也是 Starter 与 SpringBoot 建立联系的桥梁

各个类的描述

作用和描述
SpringApplication Spring Boot 应用启动的主要入口点。它负责引导应用程序,创建并配置Spring上下文
SpringApplicationRunListeners 监听器用于在应用程序的不同启动阶段接收事件通知;例如环境准备、上下文创建和应用程序启动等
ApplicationContext 这是 Spring 框架的中心接口,代表了 Spring 容器。它管理应用程序中的bean定义、解析依赖关系等
BeanDefinition 这是Spring中的一个核心概念,代表了 Spring 容器中的一个 bean 的定义,包括它的属性、构造器参数和具体的实现类等信息
ConfigurationClassPostProcessor 特殊的 BeanFactory 后置处理器,用于处理 @Configuration 注解的类,从而读取和解析应用程序的配置。
ConfigurationClassParser 用于解析@Configuration注解的类,分析@Bean方法以及@ComponentScan、@Import等注解。是最重要的解析类。
AutoConfigurationImportSelector 实现 ImportSelector 接口,在 ConfigurationClassParser # processDeferredImportSelectors 处理 spring.factories 中的 Configuration 类,是自动装配、扩展的核心组件
SpringFactoriesLoader 自定义spi的实现,读取spring.factories中的数据
BeanFactory Spring的一个核心接口,它提供了高级别的bean工厂能力,用于管理和创建应用程序中的bean
BeanDefinitionRegistry 是一个接口,提供了注册 BeanDefinition 以及查询 BeanDefinition 的能力

关键核心类: ConfigurationClassPostProcessor、ConfigurationClassParser、SpringFactoriesLoader、ConfigurationClassPostProcessor 等几个类;其他几个是 bean 的实例化。


下面的时序图给出了关键位置。

三、 关键时序图

通过后置处理器 ConfigurationClassPostProcessor 调用 ConfigurationClassParser 来解析配置类,包括读取配置类中的注解信息,比如 @Bean@ComponentScan@Import等,并将其转化为容器中管理的bean定义。

ConfigurationClassParser 是解析核心。


在 ConfigurationClassParser # processDeferredImportSelectors 将处理所有延迟的ImportSelectors

能够处理 spring.factories 中的 org.springframework.boot.autoconfigure.EnableAutoConfiguration ,是通过 importSelector # selectImports 返回 list 集合。而 importSelector 接口实现最重要的类则是AutoConfigurationImportSelector


四、桥梁纽带之 AutoConfigurationImportSelector

org.springframework.context.annotation.ConfigurationClassParser#processDeferredImportSelectors 将是建立 spring.factories 与 Spring 容器之间的桥梁,而AutoConfigurationImportSelector 是整个自动装配的纽带。

AutoConfigurationImportSelector是Spring Boot自动配置机制的关键组成部分。

  1. 自动配置类选择: AutoConfigurationImportSelector实现了Spring Framework中的ImportSelector接口,它负责在Spring Boot应用程序启动过程中选择和激活一系列的自动配置类。
  2. 读取spring.factories: 它使用SpringFactoriesLoader来读取在类路径中的META-INF/spring.factories文件的全路径名。
  3. AutoConfigurationImportSelector通过AutoConfigurationImportFilter接口实现的实例来过滤自动配置类,确保只有符合当前应用程序上下文条件的自动配置类被包含在内。

AutoConfigurationImportSelector可以智能地应用对应的配置,从而为应用程序提供了很大的灵活性和便利。


关于 AutoConfigurationImportSelector的引入过程如下:

@SpringBootApplication > @EnableAutoConfiguration > @Import(AutoConfigurationImportSelector.class)

关于 AutoConfigurationImportSelector 类图情况


通过 AutoConfigurationImportFilter 的使用,AutoConfigurationImportSelector 可以精确地控制哪些自动配置类应被激活,以及哪些应被排除,确保了自动配置的灵活性和准确性。


实现了 DeferredImportSelector 的 接口, Spring 调用其 selectImports() 方法。其中 DeferredImportSelector 继承了 ImportSelector,DeferredImportSelector 实例的 selectImports() 方法的调用时机晚于 ImportSelector 实例, 等到 @Configuration 注解中相关的业务全部都处理完了才会调用


AutoConfigurationImportSelector: 实现 ImportSelector 接口,负责读取spring.factories文件,并将符合条件的配置类名作为候选配置返回给Spring容器。

SpringFactoriesLoade r: 用于加载 spring.factories 文件中指定的工厂名。

读取过程如下所示:

****

五、全局解析时序图

图一、重点关注 springBoot 应用启动过程,以及 springBoot 和 ConfigurationClassParser 之间的时序。

图二、重点关注 spring.factories 的加载以及 和 AutoConfigurationImportSelector 之间的关系

图三、重点关注 ConfigurationClassParser 解析过程

特别说明: 解析是一个递归过程,下面的时序图只能表示逻辑思想,不是严格的顺序。

六、本章小结

  1. SpringBoot Application 包含两个核心部分:一部分 SpringBoot, 一部分 Spring framework core
  2. 其中最核心关键的是 ConfigurationClassParser,processDeferredImportSelectors 是 Starter 与 Spring 容器核心的桥梁。

到这里,对整个 Starter 的解析过程,已经有了一个大概的理解,接下来,我们会再深入地分析自动装配过程和 ConfigurationClassParser 源码解析。


七、延伸阅读 configClasses -> BeanDefinition

上面只是解析 ConfigurationClass,将其变成 Spring容器(DefaultListableBeanFactory)中的 BeanDefinition。 还需 ConfigurationClassBeanDefinitionReader 等处理。

关键代码 org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

JAVA 复制代码
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
		 ....
		do {
			parser.parse(candidates);
			 ...

			// Read the model and create bean definitions based on its content
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
           // 将 configClasses 变成 BeanDefinition
			this.reader.loadBeanDefinitions(configClasses);
			...
		}
		while (!candidates.isEmpty());
		...
	}

执行之前 this.reader.loadBeanDefinitions(configClasses);

此时 DefaultListableBeanFactory 中数量为 10

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);

执行以后。 BeanDefinition 从 10 变成 162。将所有相关 configuration 中符合的 bean 都解析成 BeanDefinition,并放入到 DefaultListableBeanFactory

注:对于 ConfigurationClassBeanDefinitionReader 的处理逻辑,可自行研究; BeanDefinition 目前还不是 class 类,还需要一系列的属性填充、初始化等过程。

特别说明, BeanDefinition 的类型,根据加载的来源方式还略有不同。

在这个部分中,我们能够明白目前还不是真正的 bean, 只是 configClasses。

相关推荐
苹果醋337 分钟前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
盛派网络小助手1 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
菠萝蚊鸭1 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪2 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0072 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生2 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl
ssr——ssss2 小时前
SSM-期末项目 - 基于SSM的宠物信息管理系统
java·ssm
一棵星2 小时前
Java模拟Mqtt客户端连接Mqtt Broker
java·开发语言
鲤籽鲲2 小时前
C# Random 随机数 全面解析
android·java·c#