当前位置: 首页 > article >正文

架构师之路--springboot核心类SpringApplication方法run的源码启动流程

SpringApplication 类 run 方法源码

    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        /**'1:加载所有的 SpringApplicationRunListeners'*/
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        Collection exceptionReporters;
        try {
        	/**'2:创建并配置当前应用将要使用的 Environment'*/
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            /**'3:SpringBoot 的 banner图 output中的图片'*/
            Banner printedBanner = this.printBanner(environment);
            /**'4:根据是否是web项目,来创建不同的ApplicationContext容器'*/
            context = this.createApplicationContext();
            /**' 新增 '*/
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            /**'6:初始化ApplicationContext'*/
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            /**'7:就是插手容器的启动'*/
            this.refreshContext(context);
            /**'8:查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行它们。'*/
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
			/**'9:执行所有SpringApplicationRunListener的started()方法。'*/
            listeners.started(context);
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

1:通过SpringFactoriesLoader查找并加载所有的 SpringApplicationRunListeners。
通过调用starting()方法通知所有的SpringApplicationRunListeners:应用开始启动了。SpringApplicationRunListeners其本质上就是一个事件发布者,它在SpringBoot应用启动的不同时间点发布不同应用事件类型(ApplicationEvent),如果有哪些事件监听者(ApplicationListener)对这些事件感兴趣,则可以接收并且处理。还记得初始化流程中,SpringApplication加载了一系列ApplicationListener吗?这个启动流程中没有发现有发布事件的代码,其实都已经在SpringApplicationRunListeners这儿实现了。

2: 创建并配置当前应用将要使用的 Environment,Environment用于描述应用程序当前的运行环境,其抽象了两个方面的内容:配置文件(profile)和属性(properties),开发经验丰富的同学对这两个东西一定不会陌生:不同的环境(eg:生产环境、预发布环境)可以使用不同的配置文件,而属性则可以从配置文件、环境变量、命令行参数等来源获取。因此,当Environment准备好后,在整个应用的任何时候,都可以从Environment中获取资源。

  • 判断Environment是否存在,不存在就创建(如果是web项目就创建 StandardServletEnvironment,否则创建
  • StandardEnvironment) 配置Environment:配置profile以及properties
    调用SpringApplicationRunListener的
  • environmentPrepared()方法,通知事件监听者:应用的Environment已经准备好

3:SpringBoot 的 banner图 output中的图片

4:根据是否是web项目,来创建不同的ApplicationContext容器

6:初始化ApplicationContext,主要完成以下工作:

  • 将准备好的Environment设置给ApplicationContext

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

  • 调用SpringApplicationRunListener的
    contextPrepared()方法,通知所有的监听者:ApplicationContext已经准备完毕

  • 将所有的bean加载到容器中

  • 调用SpringApplicationRunListener的
    contextLoaded()方法,通知所有的监听者:ApplicationContext已经装载完毕

7:调用ApplicationContext的 refresh()方法,完成IoC容器可用的最后一道工序。就是插手容器的启动

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

9:执行所有SpringApplicationRunListener的started()方法。


http://www.kler.cn/a/441195.html

相关文章:

  • Linux《基础指令》
  • 深入解析 C++17 中的 std::not_fn
  • Java---入门基础篇(上)
  • shell脚本批量修改文件名之方法(The Method of Batch Modifying File Names in Shell Scripts)
  • 渗透测试之WAF规则触发绕过规则之规则库绕过方式
  • 新年快乐!给大家带来了一份 python 烟花代码!
  • 【华为OD机试真题】【2024年E卷】数值同化-队列BFS(C++/Java/Python)
  • 网络安全考题
  • 禁用硬件合成 (Hardware Composer, HWC)
  • ChatGPT搜索全新升级,向全体用户开放,近屿智能助力AI行业发展
  • Linux:入门篇——万字长篇解析
  • 生活小妙招之UE CaptureRT改
  • Qt编译MySQL数据库驱动
  • Linux 各发行版安装 ping 命令指南
  • 解决Windows Server环境下PPTX转PDF时WebP格式图片缺失
  • 程序设计考题汇总(四:SQL练习)
  • Pytorch | 从零构建GoogleNet对CIFAR10进行分类
  • 【Linux课程学习】:第二十一弹---深入理解信号(中断,信号,kill,abort,raise,larm函数)
  • Linux学习笔记思维导图(系统调用+网络编程)
  • 信息安全实训室网络攻防靶场实战核心平台解决方案
  • 【集成部署打包】vue3+django集成部署打包成exe 文件
  • android、flutter离线推送插件,支持oppo、vivo、小米、华为
  • Tomcat HTTPS配置、域名解析及Java WAR包打包
  • Moretl品质文件采集
  • nods.js之nrm安装及使用
  • 掌握HTML, 从零开始的网页设计