SpringBoot 应用程序启动过程揭秘

原文地址:http://www.codesheep.cn/2018/09/04/springboot-startup-process/

概述
说到接触 SpringBoot 伊始,给我第一映像最深的是有两个关键元素:
这里写图片描述
对照上面的典型代码,这个两个元素分别是:

  1. @SpringBootApplication
  2. 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()方法探秘
先看看代码长啥样子:
这里写图片描述
各个主要步骤我已经标注在上图之中了,除此之外,我也按照自己的理解画了一个流程图如下所示,可以对照数字标示看一下:
这里写图片描述
我们将各步骤总结精炼如下:
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 消息,告知程序已运行起来了
至此,全流程结束!


欢迎大家加入Java高级架构/互联网(严禁培训机构、广告群,最干净的技术交流群):微信号:1083683150(备注:技术群或者4000G架构师资源)

微信平台本人收集个大量资源(4000G架构师资源,1000G大数据资源),只做分享,欢迎大家关注获取,保证免费,非任何机构

更多精彩请扫码关注微信公众号—— 名称:java版web项目 id :java_project
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值