第五节 Starter 的加载全貌

news2024/7/5 0:20:38

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容器。

SpringFactoriesLoader: 用于加载 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

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。

已同步发布到公众号:面汤放盐  第五节 Starter 的加载全貌 (qq.com)

掘金账号: 第五节 Starter 的加载全貌 - 掘金 (juejin.cn)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1685056.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Day 60 84.柱状图中最大的矩形

柱状图中最大的矩形 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 1 < heights.length <10^50 < heights[i] < 10^4 ​ 这道题很明显&…

x264码率控制基础

x264码率控制模型 x264码率控制也是基于率失真模型即,D为失真,R为码率,为拉格朗日因子,当取值较大时,倾向于低码率高失真的情况;当取值较小时,倾向于高码率低失真的情况。由拉格朗日乘数法知, 参考[1], x264采用的是高码率下码率和失真之间的关系

数据结构和算法|排序算法系列(一)|选择排序

首先需要你对排序算法的评价维度和一个理想排序算法应该是什么样的有一个基本的认知&#xff1a; 《Hello算法之排序算法》 主要内容来自&#xff1a;Hello算法11.2 选择排序 选择排序是明显的基于比较的排序。下文开始阐述选择排序的整个算法流程 算法流程 选择排序应该已…

x264 码率控制原理:x264_ratecontrol_start 函数

x264_ratecontrol_start 函数 函数原理 函数功能:编码一帧之前,为当前帧选择一个量化 QP,属于帧级别码率控制;这对于控制视频质量和文件大小至关重要。通过调整QP,编码器可以在保持视频质量的同时,尽可能减小输出文件的大小。函数参数:x264_t *h: 编码器上下文结构体指…

贴片 RS8752XK 封装SOP-8 250MHz,2通道高速运放

传感器信号放大&#xff1a;在传感器应用中&#xff0c;RS8752XK可以用于放大微弱的传感信号&#xff0c;如压力、温度、光强等传感器的信号。 数据采集系统&#xff1a;在数据采集设备中&#xff0c;RS8752XK可以用于放大和调理模拟信号&#xff0c;以供模数转换器&#xff0…

abs(-2147483648) == 2147483648?

从数学意义上&#xff0c;这是对的。但是&#xff0c;就怕但是。 #include int main() {long long v;v abs(-2147483648);printf("%lld\n", v);return 0; } 输出: -2147483648 我们从source code中一一解开. /* Return the absolute value of I. */ int abs (…

Mist-开源macOS系统版本安装包管理工具

Mist 用于下载 macOS 系统安装包的工具&#xff0c;可下载macOS 固件 / 安装程序。 需要经常下载macOS的可以体验一下。 可以在底部选择显示 macOS 的 Beta 版本 筛选出与当前 Mac 兼容的 macOS 版本 想了解更多可访问项目地址&#xff1a; https://github.com/ninxsoft/Mis…

一文了解微服务

微服务架构是一种将应用程序划分为一组小型、独立的服务的方法&#xff0c;这些服务运行在自己的进程中&#xff0c;通常通过网络进行通信。微服务架构的主要优点是可以提高应用程序的灵活性和可扩展性&#xff0c;同时也使得开发、部署和维护更加容易。本文将介绍微服务架构的…

Redis实践—全国地址信息缓存

一、背景 在涉及全国地址的应用中&#xff0c;地址信息通常被频繁地查询和使用&#xff0c;例如电商平台、物流系统等。为了提高系统性能和减少对数据库的访问压力&#xff0c;可以使用缓存来存储常用的地址信息&#xff0c;其中 Redis 是一个非常流行的选择。 本次在一个企业入…

【Text2SQL 经典模型】SQLNet

论文&#xff1a;SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning ⭐⭐⭐⭐ Code: SQLNet | paperwithcodeSQLNet| GitHub 一、论文速读 这篇论文强调了一个问题&#xff1a;order-matters problem —— 意思是说&#xff0c;对…

【机器学习】—机器学习和NLP预训练模型探索之旅

目录 一.预训练模型的基本概念 1.BERT模型 2 .GPT模型 二、预训练模型的应用 1.文本分类 使用BERT进行文本分类 2. 问答系统 使用BERT进行问答 三、预训练模型的优化 1.模型压缩 1.1 剪枝 权重剪枝 2.模型量化 2.1 定点量化 使用PyTorch进行定点量化 3. 知识蒸馏…

HQL面试题练习 —— 品牌营销活动天数

题目来源&#xff1a;小红书 目录 1 题目2 建表语句3 题解 1 题目 有营销活动记录表&#xff0c;记录了每个品牌每次营销活动的开始日期和营销活动的结束日期&#xff0c;现需要统计出每个品牌的总营销天数。 注意&#xff1a; 1:苹果第一行数据的营销结束日期比第二行数据的营…

系统思考—跳出症状看全局

今年的《系统思考—跳出症状看全局》课程不断进行了迭代优化。通过一个企业的真实案例&#xff0c;我们与学员共同探讨了线性思考与系统思考的区别&#xff0c;并学习了如何从全局角度做出更加明智的决策&#xff0c;一切就绪&#xff0c;期待学员的共创。

xxe漏洞--xml外部实体注入漏洞

1.xxe漏洞介绍 XXE&#xff08;XML External Entity Injection&#xff09;是一种攻击技术&#xff0c;它允许攻击者注入恶意的外部实体到XML文档中。如果应用程序处理XML输入时未正确配置&#xff0c;攻击者可以利用这个漏洞访问受影响系统上的敏感文件、执行远程代码、探测内…

操作系统底层运行原理 —— 基于线程安全的消息机制

前言 学过Android应用开发的大概都知道Handler这个东东&#xff0c;这也是面试中老生常谈的问题。其实不仅仅是Android&#xff0c;iOS以及PC的操作系统&#xff0c;底层也离不开消息机制。这个属于生产消费者问题。 什么是生产者消费者模式 生产者消费者模式&#xff08;Pr…

【UE Websocket】“WebSocket Server”插件使用记录

1. 在商城中下载“WebSocket Server”插件 该插件具有如下节点&#xff0c;基本可以满足WebSocket服务端的所有需求 2. 如果想创建一个基本的服务端&#xff0c;我们可以新建一个actor蓝图&#xff0c;添加如下节点 3. UE运行后&#xff0c;我们可以使用在线的websocket测试助手…

使用MicroPython和pyboard开发板(15):使用LCD和触摸传感器

使用LCD和触摸传感器 pybaord的pyb对LCD设备也进行了封装&#xff0c;可以使用官方的LCD显示屏。将LCD屏连接到开发板&#xff0c;连接后。 使用LCD 先用REPL来做个实验&#xff0c;在MicroPython提示符中输入以下指令。请确保LCD面板连接到pyboard的方式正确。 >>…

认识NXP新型微处理器:MCX工业和物联网微控制器

目录 概述 1 MCX工业和物联网微控制器介绍 2 MCX 系列微控制器类型 2.1 MCX N系列微控制器 2.1.1 主要特征 2.1.2 MCX N系列产品 2.1.3 MCX N9xx和N5xx MCU选型表 2.2 MCX A系列微控制器 2.2.1 主要特征 2.2.2 MCX A系列产品 2.2.3 MCX A MCU的架构 2.3 MCX W系…

Unity射击游戏开发教程:(24)创造不同的敌人

在这篇文章中,我们将讨论添加一个可以承受多次攻击的新敌人和一些动画来使事情变得栩栩如生。敌人没有任何移动或射击行为。这将有助于增强未来敌人的力量。 我们将声明一个 int 来存储敌人可以承受的攻击数量,并将其设置为 3。