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


概述

说到接触 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 实例的初始化

我们对照代码来看:

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

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

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

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

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



SpringApplication 的run()方法探秘

先看看代码长啥样子:

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

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

  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 消息,告知程序已运行起来了

至此,全流程结束!



后记

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

  • My Personal Blog
  • 我的半年技术博客之路


SpringBoot 应用程序启动过程探秘相关推荐

  1. onresize事件会被多次触发_玩转SpringBoot之通过事件机制参与SpringBoot应用的启动过程...

    生命周期和事件监听 一个应用的启动过程和关闭过程是归属到"生命周期"这个概念的范畴. 典型的设计是在启动和关闭过程中会触发一系列的"事件",我们只要监听这些事件 ...

  2. Delta3d框架学习--程序启动过程详解

    一个Delta3d程序启动过程详解 一.初始化一个dtGame::GameApplication的实例,dtGame::GameApplication* app = new dtGame::GameA ...

  3. iOS程序启动过程笔记

    CHENYILONG Blog 笔记 一.iOS程序的完整启动过程(有storyboard) 1.先执行main函数,main内部会调用UIApplicationMain函数 2.UIApplicat ...

  4. Android应用程序启动过程源代码分析(5)

    Step 35. MainActivity.onCreate 这个函数定义在packages/experimental/Activity/src/shy/luo/activity/MainActivi ...

  5. spring容器_Spring 容器的启动过程探秘

    一. 前言 Spring家族特别庞大,对于开发人员而言,要想全面征服Spring家族,得花费不少的力气.俗话说,打蛇打七寸,那么Spring家族的"七寸"是什么呢?我心目中的答案一 ...

  6. 飞鸽传书源码分析-程序启动过程

    本文章是在飞鸽传书的2.06源码基础上分析 飞鸽传书源码运行流程如下,本篇文章只说明了飞鸽传书的启动过程,对于飞鸽伟书的消息机制及菜单加载等功能都不在本篇文章范围之内. 1. WinMain函数 [c ...

  7. Framework学习(五)应用程序启动过程

    注释1处设置Flag为Intent.FLAG_ACTIVITY_NEW_TASK,这样根Activity会在新的任务栈中启动. 注释2处调用了Activity的startActivity函数. fra ...

  8. Springboot在程序启动之前特殊处理

    我们平时使用springboot都是使用main函数直接启动的,例如 @SpringBootApplication public class Application {public static vo ...

  9. 11.小白初学日记 STM32F429 HAL库 STM32程序启动过程

    大家好,怀着激动地小心,激动地小手,我们来了. 今天我想给大家分享一个我自己的错误点.来警示大家. 刚才写我按键例程程序的时候,我自己来写的,发现启动不了,终于找到了原因,大家一起来看下. while ...

最新文章

  1. Discovering Gold LightOJ - 1030[概率dp或者记忆化搜索]
  2. android 保存崩溃信息,Android保存每次运行崩溃报告的日志
  3. acwing算法题--完全背包问题
  4. Linux下监控磁盘io,如何在Linux下监控磁盘IO?
  5. java文本编辑器 运行_能编译运行java的简单文本编辑器
  6. DotNetCore跨平台~Dockerfile的解释
  7. mysql gtid基础_MySQL 基础知识梳理学习(四)----GTID
  8. dede定义全局变量(include/common.inc.php)及调用方式
  9. 14种DLL注入技术
  10. VOA上一句英语的翻译
  11. 为什么还有6亿中国人仍不放弃QQ?
  12. 叔叔阿姨,我真的不会修电脑
  13. python库阿里云镜像大全
  14. 华为云服务之存储服务
  15. VCS(DVE)仿真波形的存储和打开.vpd
  16. 投资人为什么盯上了这些“小巨人”?
  17. 帝国时代3如何快速实现增加主城生命值
  18. Java到底能干什么?
  19. 1.PhotoShop缩小图片的三种方式
  20. treeview demo

热门文章

  1. plsql tables 没有表_天长视唱练耳辅导班收费表,安徽高考音乐培训学校,你知道吗...
  2. python流行的爬虫框架_Python爬虫相关框架
  3. Oracle大的存储层次体系,Oracle 数据库中的逻辑存储层次体系
  4. char-embedding是如何输入到模型的
  5. 数学实验matlab课后习题答案,matlab数学实验教程答案
  6. 一般计算机系统中的文件系统采用,南昌大学2001年考研专业课试卷操作系统A
  7. 信息系统项目管理师:第7章:项目成本管理(1)-章节重点
  8. 笔记-项目人力资源管理-建设项目团队
  9. Electron中提示:Refused to execute inline event handler because it violates
  10. Vue实现仿音乐播放器13-实现音乐榜单跳转显以及播放效果