SpringBoot 应用程序启动过程探秘
概述
说到接触 SpringBoot 伊始,给我第一映像最深的是有两个关键元素:
对照上面的典型代码,这个两个元素分别是:
- @SpringBootApplication
- SpringApplication 以及 run() 方法
关于 @SpringBootApplication 注解的剖析已经在上文:《SpringBoot 中 @SpringBootApplication注解背后的三体结构探秘》 中完成了,其实它背后就是一个三体结构,只是 SpringBoot给了其一个包装而已。那么本文我们就来看看这个 SpringApplication 以及 run() 方法 到底是个什么鬼,它背后又隐藏了哪些奥秘呢?
本文内容脑图如下:
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()方法探秘
先看看代码长啥样子:
各个主要步骤我已经标注在上图之中了,除此之外,我也按照自己的理解画了一个流程图如下所示,可以对照数字标示看一下:
我们将各步骤总结精炼如下:
通过
SpringFactoriesLoader加载META-INF/spring.factories文件,获取并创建SpringApplicationRunListener对象然后由
SpringApplicationRunListener来发出 starting 消息创建参数,并配置当前 SpringBoot 应用将要使用的 Environment
完成之后,依然由
SpringApplicationRunListener来发出 environmentPrepared 消息创建
ApplicationContext初始化
ApplicationContext,并设置 Environment,加载相关配置等由
SpringApplicationRunListener来发出contextPrepared消息,告知SpringBoot 应用使用的ApplicationContext已准备OK将各种 beans 装载入
ApplicationContext,继续由SpringApplicationRunListener来发出 contextLoaded 消息,告知 SpringBoot 应用使用的ApplicationContext已装填OKrefresh ApplicationContext,完成IoC容器可用的最后一步
由
SpringApplicationRunListener来发出 started 消息完成最终的程序的启动
由
SpringApplicationRunListener来发出 running 消息,告知程序已运行起来了
至此,全流程结束!
后记
SpringBoot 应用程序启动过程探秘的更多相关文章
- Envoy 源码分析--程序启动过程
目录 Envoy 源码分析--程序启动过程 初始化 main 入口 MainCommon 初始化 服务 InstanceImpl 初始化 启动 main 启动入口 服务启动流程 LDS 服务启动流程 ...
- 【玩转SpringBoot】通过事件机制参与SpringBoot应用的启动过程
生命周期和事件监听 一个应用的启动过程和关闭过程是归属到“生命周期”这个概念的范畴. 典型的设计是在启动和关闭过程中会触发一系列的“事件”,我们只要监听这些事件,就能参与到这个过程中来. 要想监听事件 ...
- 【玩转SpringBoot】SpringBoot应用的启动过程一览表
SpringBoot应用的启动方式很简单,就一行代码,如下图01: 其实这行代码背后主要执行两个方法,一个是构造方法,一个是run方法. 构造方法主要内容就是收集一些数据,和确认一些信息.如下图02: ...
- 深入理解UIApplication和ios程序启动过程
在深入理解UIApplication前我们先了解ios程序的启动过程: UIApplication类在ios里面为app的管理和协调提供一个集中的点,每一个app有一个UIApplication的实例 ...
- [转] - C++程序启动过程
先说编译.链接过程1.预编译展开宏2.为每一个.cxx源文件编译一个目标文件3.编译器合成这些目标文件成一个库文件,同时解析可以找到的符号引用4.连接器把目标的库文件和所需要的引用的静.动态链接库进行 ...
- [iOS基础控件 - 6.10.6] UIApplicationDelegate & 程序启动过程
A.概念 1.移动app非常容易受到其他的系统.软件事件的干扰,如来电.锁屏 2.app受到干扰的时候,UIApplication会通知delegate,来代理处理干扰事件 3.delegate可以处 ...
- Android应用程序启动过程源代码分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6689748 前文简要介绍了Android应用程 ...
- Android 应用程序启动过程源代码分析
本文转自:http://blog.csdn.net/luoshengyang/article/details/6689748 前文简要介绍了Android应用程序的Activity的启动过程.在And ...
- Android程序启动过程深入解析
当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么样的? 什么是Linux内核? 桌面系统linux内核与Android系统linux内核有什么区别? 什么是引导装载程序 ...
随机推荐
- 字符串格式的Url的截取
一,我们先在看在页面上获取的URL的处理,如下方法: //获取全部URL string Url = Request.Url.ToString(); Url += "</br>&q ...
- js 页面跳转 新窗口打开
页面跳转:Window.showModalDialog(url,width,height); 弹出一个html文档的模式对话框Parent.window.document.location.href ...
- Linux拓展练习部分--输入输出 / find部分 /基础拓展2
目录 输入输出部分 find部分 基础阶段-拓展练习2 输入输出部分 1.输入时间命令"date"将当前系统时间输出到/data/1.txt [root@centos7 ~]# d ...
- linux CentOS7 nginx nginx-rtmp-module搭建直播
直播配置 1. 安装 Nginx 依赖软件 yum -y install gcc gcc-c++ autoconf automake make yum -y install zlib zlib-dev ...
- @HttpEntity参数(怪异)
1).在Controller中写 与@RequestBody请求体对应 @HttpEntity更强大,不光有请求体,还能获取请求头 @RequestMapping("/test02" ...
- proxy汇总-1
1.apt-get的proxy 新建/etc/apt/apt.conf.d目录下新建10proxy文件,添加: Acquire::http::proxy"http://xx.xx.xx.xx ...
- MYSQL中判断函数有哪些
新建一张客户表,如下:sex:1-男,2-女,3-未知:level是客户的级别:1-超级VIP客户,2-VIP客户,3-普通客户 方式一:case函数:流程控制函数 用法一: CASE express ...
- 理解Java主函数中的"String[] args"
public class Understand_String_args { public static void main(String[] args) { System.out.printf(&qu ...
- docker 运行jenkins及vue项目与springboot项目(二.docker运行jenkins为自动打包运行做准备)
docker 运行jenkins及vue项目与springboot项目: 一.安装docker 二.docker运行jenkins为自动打包运行做准备 三.jenkins的使用及自动打包vue项目 四 ...
- 微信JS-SDK接口上传图片以及wx.config的配置
最近做的微信网页要实现一个上传图片的功能,倒腾了半天终于搞好了,具体的步骤可以查看微信官方文档https://developers.weixin.qq.com/doc/offiaccount/OA_W ...