SpringBoot 应用程序启动过程探秘

简介:

Profile

本文共 946字,阅读大约需要 3分钟 !


概述

说到接触 SpringBoot 伊始,给我第一映像最深的是有两个关键元素:

SpringBoot 的两个关键元素

对照上面的典型代码,这个两个元素分别是:

  • @SpringBootApplication
  • SpringApplication 以及 run() 方法

关于 @SpringBootApplication 注解的剖析已经在上文:《SpringBoot 中 @SpringBootApplication注解背后的三体结构探秘》 中完成了,其实它背后就是一个三体结构,只是 SpringBoot给了其一个包装而已。那么本文我们就来看看这个 SpringApplication 以及 run() 方法 到底是个什么鬼,它背后又隐藏了哪些奥秘呢?

注: 本文首发于 My Personal Blog,欢迎光临 小站

本文内容脑图如下:

本文内容脑图


SpringApplication 惊鸿一瞥

SpringApplication 这个类应该算是 SpringBoot 框架 的“创新”产物了,原始的 Spring中并没有这个类,SpringApplication 里面封装了一套 Spring 应用的启动流程,然而这对用户完全透明,因此我们上手 SpringBoot 时感觉简洁、轻量。

一般来说默认的 SpringApplication 执行流程已经可以满足大部分需求,但是 若用户想干预这个过程,则可以通过 SpringApplication 在流程某些地方开启的 扩展点 来完成对流程的扩展,典型的扩展方案那就是使用 set 方法。

我们来举一个栗子,把我们天天司空见惯的 SpringBoot 应用的启动类来拆解一下写出来:

@SpringBootApplication
public class CodeSheepApplication {
    public static void main( String[] args ) {
        // SpringApplication.run( CodeSheepApplication.class args ); // 这是传统SpringBoot应用的启动,一行代码搞定,内部默认做了很多事
        SpringApplication app = new SpringApplication( CodeSheepApplication.class );
        app.setXXX( ... ); // 用户自定的扩展在此 !!!
        app.run( args );
    }
}

这样一拆解后我们发现,我们也需要先构造 SpringApplication 类对象,然后调用该对象的 run() 方法。那么接下来就讲讲 SpringApplication 的构造过程 以及其 run() 方法的流程,搞清楚了这个,那么也就搞清楚了SpringBoot应用是如何运行起来的!


SpringApplication 实例的初始化

我们对照代码来看:

SpringApplication 实例的初始化代码

四个关键的步骤已标注在图中,分别解释如下:

  • 推断应用的类型:创建的是 REACTIVE应用、SERVLET应用、NONE 三种中的某一种

推断应用的类型

  • 使用 SpringFactoriesLoader查找并加载 classpath下 META-INF/spring.factories文件中所有可用的 ApplicationContextInitializer

ApplicationContextInitializer 加载

  • 使用 SpringFactoriesLoader查找并加载 classpath下 META-INF/spring.factories文件中的所有可用的 ApplicationListener

ApplicationListener 加载

  • 推断并设置 main方法的定义类

推断并设置main方法的定义类



SpringApplication 的run()方法探秘

先看看代码长啥样子:

SpringApplication 的run()方法背后的奥秘

各个主要步骤我已经标注在上图之中了,除此之外,我也按照自己的理解画了一个流程图如下所示,可以对照数字标示看一下:

SpringBoot 应用启动流程图

我们将各步骤总结精炼如下:

  1. 通过 SpringFactoriesLoader 加载 META-INF/spring.factories 文件,获取并创建 SpringApplicationRunListener 对象
  2. 然后由 SpringApplicationRunListener 来发出 starting 消息
  3. 创建参数,并配置当前 SpringBoot 应用将要使用的 Environment
  4. 完成之后,依然由 SpringApplicationRunListener 来发出 environmentPrepared 消息
  5. 创建 ApplicationContext
  6. 初始化 ApplicationContext,并设置 Environment,加载相关配置等
  7. SpringApplicationRunListener 来发出 contextPrepared 消息,告知SpringBoot 应用使用的 ApplicationContext 已准备OK
  8. 将各种 beans 装载入 ApplicationContext,继续由 SpringApplicationRunListener 来发出 contextLoaded 消息,告知 SpringBoot 应用使用的 ApplicationContext 已装填OK
  9. refresh ApplicationContext,完成IoC容器可用的最后一步
  10. SpringApplicationRunListener 来发出 started 消息
  11. 完成最终的程序的启动
  12. SpringApplicationRunListener 来发出 running 消息,告知程序已运行起来了

至此,全流程结束!



后记

由于能力有限,若有错误或者不当之处,还请大家批评指正,一起学习交流!



目录
相关文章
|
1月前
|
Java
springboot如何确定当前应用程序是响应式的还是非响应式的
springboot如何确定当前应用程序是响应式的还是非响应式的
springboot如何确定当前应用程序是响应式的还是非响应式的
|
6月前
|
XML Java 数据格式
SpringBoot的启动过程
启动详解 SpringBoot的启动分为两个部分: 构造SpringApplication 执行run方法 构造SpringApplication 我们先来整体看看: 加入我们当前启动类如下: 可以发现大致做了以下几件事: 设置BeanDefinition的主源 推断应用类型 设置ApplicationContext 初始化器 设置监听器 推断著主启动类 接下来我们详细的看看每一个步骤: 第一步:记录 BeanDefinition 源 大家知道我们的Spring容器刚开始内部的BeanFactory是空的,它要从各个源头去寻找BeanDefinition, 这些源有可能来自
63 1
|
7月前
|
Java 应用服务中间件 开发工具
深入了解Spring Boot:简化Java应用程序开发的利器
Spring Boot是一款用于构建Java应用程序的框架,它旨在简化应用程序的开发过程,同时提供了强大的功能和灵活性。无论是构建小型微服务还是大型企业级应用,Spring Boot都可以帮助您快速启动和开发项目。本文将深入介绍Spring Boot的关键概念和功能,以便您能够更好地利用这个强大的工具。
|
5月前
|
存储 Java API
如何在Spring Boot应用程序中使用华为云的OBS云存储来上传和删除图片?
如何在Spring Boot应用程序中使用华为云的OBS云存储来上传和删除图片?
125 1
|
6天前
|
Java 应用服务中间件 Maven
【SpringBoot系列】第一课:构建一个简单的SpringBoot应用程序
【4月更文挑战第3天】构建第一个SpringBoot应用程序
22 1
|
4月前
|
Java 测试技术 应用服务中间件
使用 Spring Boot 构建应用程序
本指南提供了 Spring Boot 如何帮助您加速应用程序开发的示例。
|
2月前
|
存储 开发框架 算法
|
3月前
|
Java 应用服务中间件 微服务
springboot详细启动过程
springboot详细启动过程
|
8月前
|
Java
如何在SpringBoot启动过程中,进行自定义操作?
如何在SpringBoot启动过程中,进行自定义操作?
40 0
|
3月前
|
前端开发 Java 测试技术
SpringBoot - 应用程序测试方案
SpringBoot - 应用程序测试方案
53 0