SpringBoot启机流程整理

2024-06-14 09:32

本文主要是介绍SpringBoot启机流程整理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近抽空学习了SpringBoot的代码,本次主要对SpringBoot的启动流程进行总结。如下代码所示,SpringBoot启机可分为两个大步骤:首先是初始化一个SpringApplication对象,然后执行该对象的run()。本文将根据这两个步骤分两部分总结。

1.SpringApplication初始化流程

进入SpringApplication对象,可以如下代码:

该初始化的主要目的是从SpringBoot的spring.factories配置文件中,找到ApplicationContextInitializer和ApplicationListener两个接口的实现类名称,便于后期生成对应的实例。其中:ApplicationContextInitializer的主要目的是在ConfigurableApplicationContext做refresh之前,对ConfigurableApplicationContext实例做进一步的设置或处理。ApplicationListener是Spring框架对Java事件监听机制的一种框架实现,主要用于启机流程中对各个步骤的事件进行监听与处理。

SpringApplication对象通过方法getSpringFactoriesInstances()以反射的形式加载对应的类,具体流程如下:

1.通过SpringFactoriesLoader.loadFactoryNames()从所有jar包的"META-INF/spring.factories"配置文件中加载类名称。

其中,类加载器默认采用AppClassLoader:

SpringApplication调用createSpringFactoriesInstances()方法,根据入参“type”,完成类的加载与初始化:

至此,Application对象完成了主要的初始化流程,为后续的启机流程奠定了基础。

2.SpringBoot启机流程

真正执行SpringBoot启机流程的是Application的run()方法:

1.通知监听器,SpringBoot开始启动

声明一个SpringApplicationRunListeners对象,并通过SpringFactoriesLoader查找所有spring.factories中key为“org.springframework.boot.SpringApplicationRunListener”的值,并加载对应的接口类。SpringApplicationRunListeners通过调用starting()方法通知所有的SpringApplicationRunListener应用开始启动了。

SpringApplicationRunListeners本质上就是一个事件发布者的包装类,在SpringBoot应用启动的不同时间点发布不同应用事件类型(ApplicationEvent),如果有哪些事件监听者(ApplicationListener)对这些事件感兴趣,则可以接收并且处理。SpringApplicationRunListeners对象中包含一个真正事件发布者的类对象EventPublishingRunListener,该类实现了SpringApplicationRunListener,并实现了其方法,用于在启机过程中的不同阶段发布对应的通知:

此处发布了一个SpringBoot开始启动事件:

2.创建并配置Environment

Environment用于描述SpringBoot的运行环境,其配置主要来源于两个方面:配置文件(profile)和属性(properties)。其中不同的环境(eg:生产环境、预发布环境)可以使用不同的配置文件,而属性则可以从配置文件、环境变量、命令行参数等来源获取。当Environment准备好后,在整个SpringBoot应用的任何时候,都可以从Environment中获取资源。该部分的实现代码如下:

主要实现包括了两部分:

  1. 配置Environment:从profile以及properties读取配置到对象中,供后续使用。
  2. 调用SpringApplicationRunListener的environmentPrepared()方法,通知事件监听者进行事件处理。

3.控制台打印Banner

该步主要是从项目路径下读取“banner.txt”,实现自定义启动图形,如果没有则默认使用SpringBoot的启机图形。

4.创建ApplicationContext容器

根据不同的项目类型,创建不同的ApplicationContext上下文容器。

其中项目类型包括下面三种:

5.创建启机异常处理对象

从spring.factories中读取配置的异常处理类名称,并初始化。如果SpringBoot启机异常,则用于分析 、汇报异常信息。代码执行流程类似事件监听器。

6.ApplicationContext上下文预处理

该流程的实现代码如下:

  1. 将上文已经加载的Environment赋值给ApplicationContext。

  2. 遍历调用所有的ApplicationContextInitializer的initialize()方法,对已经创建好的ApplicationContext进行进一步的处理

  3. 通过SpringApplicationRunListener的contextPrepared()方法,通知所有的监听者ApplicationContext已经准备完毕

  4. 将所有的bean加载到容器中

  5. 通过SpringApplicationRunListener的contextLoaded()方法,通知所有的监听者ApplicationContext已经装载完毕

7.刷新IoC容器

容器刷新的执行设计以下流程:

其中:

  1. invokeBeanFactoryPostProcessors()方法会实例化和调用所有 BeanFactoryPostProcessor。BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 时对外暴露的扩展点,Spring IoC 容器允许 BeanFactoryPostProcessor 在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。这里有个特殊的BeanFactoryPostProcessor 称作BeanDefinitionRegistryPostProcessor,其 继承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义,其对应的Class为ConfigurationClassPostProcessor。ConfigurationClassPostProcessor用于解析处理各种注解,包括:@Configuration、@ComponentScan、@Import、@PropertySource、@ImportResource、@Bean。当处理@import注解的时候,就会调用这一小节中的EnableAutoConfigurationImportSelector.selectImports()来完成自动配置功能。(更多自动配置功能请见“自定义实现SpringBoot的starter”)

  2. registerBeanPostProcessors()方法会实例化和注册所有 BeanPostProcessor。BeanFactoryPostProcessor 是针对 BeanFactory 的扩展,主要用在 bean 实例化之前,读取 bean 的定义,并可以修改它。BeanPostProcessor 是针对 bean 的扩展,主要用在 bean 实例化之后,执行初始化方法前后,允许开发者对 bean 实例进行修改。

注:该步骤是Ioc容器加载Bean的核心流程,流程太长,没完全消化,感兴趣的小伙伴可以查阅大神的文章“Spring IoC源码学习”

8.ApplicationContext上下文刷新后处理

该方法为预留接口,当前SpringBoot启机流程并未实现

9.通知监听器,SpringBoot启动完成

10.执行Runner

查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行。

11.通知监听器,SpringBoot正在运行

12.启机异常处理

如果启机流程执行过程中,遇到了异常情况,则由handleRunFailure()方法进行处理,包括:

  1. 异常退出码处理

  2. 通知监听器,SpringBoot启动时异常

  3. 汇报异常并打印log

参考资料:

  1. Spring IoC源码学习

  2. 最棒SpringBoot干活总结

这篇关于SpringBoot启机流程整理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1060020

相关文章

springboot集成easypoi导出word换行处理过程

《springboot集成easypoi导出word换行处理过程》SpringBoot集成Easypoi导出Word时,换行符n失效显示为空格,解决方法包括生成段落或替换模板中n为回车,同时需确... 目录项目场景问题描述解决方案第一种:生成段落的方式第二种:替换模板的情况,换行符替换成回车总结项目场景s

SpringBoot集成redisson实现延时队列教程

《SpringBoot集成redisson实现延时队列教程》文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费... 目录1、先给项目导入Redisson依赖2、配置redis3、创建 RedissonConfig 配

SpringBoot中@Value注入静态变量方式

《SpringBoot中@Value注入静态变量方式》SpringBoot中静态变量无法直接用@Value注入,需通过setter方法,@Value(${})从属性文件获取值,@Value(#{})用... 目录项目场景解决方案注解说明1、@Value("${}")使用示例2、@Value("#{}"php

SpringBoot分段处理List集合多线程批量插入数据方式

《SpringBoot分段处理List集合多线程批量插入数据方式》文章介绍如何处理大数据量List批量插入数据库的优化方案:通过拆分List并分配独立线程处理,结合Spring线程池与异步方法提升效率... 目录项目场景解决方案1.实体类2.Mapper3.spring容器注入线程池bejsan对象4.创建

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF