SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第1张图片

前言

spring作为主流的 Java Web 开发的开源框架,是Java 世界最为成功的框架,持续不断深入认识spring框架是Java程序员不变的追求。

在之前的博客中,我们分析了@SpringBootApplication注解的作用,阐述了分布式架构下自动引入其他模块的类的方法

@SpringBootApplication注解的理解——如何排除自动装配 & 分布式情况下如何自动加载 & nacos是怎么被发现的

在这里插入图片描述

本篇博客介绍SpringBoot项目是怎么run跑起来的,从SpringApplication.run()方法入手,进行了启动流程的拆解,分析了监听的类SpringApplicationRunListeners,事件生命周期相关的类EventPublishingRunListener,配置相关的类ConfigurableEnvironment。

目录

  • 前言
  • 引出
  • 拆解SpringBoot启动流程
  • 启动流程的拆解
    • 1.启动代码
    • 2.进入run方法
    • 3.SpringApplication对象
    • 4.设置监听器
    • 5.再跟踪到run方法
  • 相关的类深入分析
    • SpringApplicationRunListener
    • EventPublishingRunListener
    • 生命周期和对应事件
    • ConfigurableEnvironment
  • 总结

引出


1.从SpringApplication.run()方法入手,进行了启动流程的拆解;
2.分析了监听的类SpringApplicationRunListeners,事件生命周期相关的类EventPublishingRunListener;
3.配置相关的类ConfigurableEnvironment。

拆解SpringBoot启动流程

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第2张图片

启动流程的拆解

1.启动代码

项目主启动类代码

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第3张图片

2.进入run方法

点击查看run方法实现

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第4张图片

再跟踪到run方法中

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第5张图片

3.SpringApplication对象

可以看到此处在创建SpringApplication对象,然后调用run方法,先查看构造方法代码

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第6张图片

在该方法中调用另外一个构造方法,如下

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第7张图片

4.设置监听器

设置监听器,此处设置11个监听器

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第8张图片

5.再跟踪到run方法

然后再跟踪到run方法

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第9张图片

    public ConfigurableApplicationContext run(String... args) {
        long startTime = System.nanoTime();
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        
        // 创建所有 Spring 运行监听器并发布应用启动事件
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        // 启动各个SpringApplicationRunListener 监听器实例(EventPublishingRunListener)
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            // 初始化默认应用参数类
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            
            // 根据运行监听器和应用参数来准备 Spring 环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            
            // 创建 Banner 打印类
            Banner printedBanner = this.printBanner(environment);
            
            // 创建应用上下文
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            // 准备应用上下文
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            // 刷新应用上下文      
            this.refreshContext(context);
            
            // 应用上下文刷新后置处理  空操作
            this.afterRefresh(context, applicationArguments);
            
            // 止计时监控,和开始的纳秒数相减
            Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
            
            // 输出日志记录执行主类名、时间信息
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
            }

            // 发布应用上下文启动完成事件
            listeners.started(context, timeTakenToStartup);
            
            // 执行所有 Runner 运行器
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            this.handleRunFailure(context, var12, listeners);
            throw new IllegalStateException(var12);
        }

        try {
            // 发布应用上下文就绪事件
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            listeners.ready(context, timeTakenToReady);
            
            // 返回应用上下文
            return context;
        } catch (Throwable var11) {
            this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var11);
        }
    }

相关的类深入分析

SpringApplicationRunListener

SpringApplicationRunListeners

SpringApplicationRunListeners中封装了多个SpringApplicationRunListener,这些监听器用来在整个启动流程中接收不同执行点事件通知的监听者,SpringApplicationRunListener接口规定了SpringBoot的生命周期,在各个生命周期广播相应的事件,调用实际的ApplicationListener类。

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第10张图片

public interface SpringApplicationRunListener {
    // run方法开始执行时
    default void starting() {
    }
    // Environment准备好之后
    default void environmentPrepared(ConfigurableEnvironment environment) {
    }
    // ApplicationContext准备好之后
    default void contextPrepared(ConfigurableApplicationContext context) {
    }
    // ApplicationContext加载完成
    default void contextLoaded(ConfigurableApplicationContext context) {
    }
    // run方法启动完成,回调ApplicationRunner和CommandLineRunner之前
    default void started(ConfigurableApplicationContext context) {
    }
    // run方法执行完成,马上出方法栈时
    default void running(ConfigurableApplicationContext context) {
    }
    // 运行异常时,执行的逻辑
    default void failed(ConfigurableApplicationContext context, Throwable exception) {
    }
}

EventPublishingRunListener

  • EventPublishingRunListener

Spring Boot定义的SpringApplicationRunListener实现类只有EventPublishingRunListener,主要是定义了其生命周期,并且在Spring Boot启动过程中完成回调。

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第11张图片

进入查看

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第12张图片

在构造函数中赋值了ApplicationContext和args,并且创建了SimpleApplicationEventMulticaster事件发送器。在SpringApplicationContext的refresh时会创建SimpleApplicationEventMulticaster,现在只是先创建出来,待执行refresh时会用到。

生命周期和对应事件

SpringApplicationRunListener生命周期和对应事件发送类型为:

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第13张图片

生命周期 对应事件
starting ApplicationStartingEvent
environmentPrepared ApplicationEnvironmentPreparedEvent
contextPrepared ApplicationContextInitializedEvent
contextLoaded ApplicationPreparedEvent
started ApplicationStartedEvent
running ApplicationReadyEvent
failed ApplicationFailedEvent

ApplicationArguments

获取程序启动参数,例如VM参数

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第14张图片

ConfigurableEnvironment

ConfigurableEnvironment

ConfigurableEnvironment不仅提供了配置文件解析的数据,以及配置文件名称,还提供了PropertySource数据。其实配置文件的解析出来的数据,也是封装成了PropertySource放在ConfigurableEnvironment中

ConfigurableEnvironment是spring中非常重要的角色,可以通过它获得activeProfiles,来判断我们所使用的环境是dev还是test或者prod等等。还可以根据getProperty拿到配置中的信息并且提供类型转换功能,以及获取系统环境变量等信息。

SpringApplication.run(OrderApp.class)——拆解SpringBoot启动流程,run方法的拆解 & SpringBoot是怎么跑起来的?_第15张图片

总结


1.从SpringApplication.run()方法入手,进行了启动流程的拆解;
2.分析了监听的类SpringApplicationRunListeners,事件生命周期相关的类EventPublishingRunListener;
3.配置相关的类ConfigurableEnvironment。

你可能感兴趣的:(SpringBoot,spring,boot,后端,java)