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

在这里插入图片描述

前言

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

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

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

在这里插入图片描述

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

引出


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

拆解SpringBoot启动流程

在这里插入图片描述

启动流程的拆解

1.启动代码

项目主启动类代码

在这里插入图片描述

2.进入run方法

点击查看run方法实现

在这里插入图片描述

再跟踪到run方法中

在这里插入图片描述

3.SpringApplication对象

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

在这里插入图片描述

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

在这里插入图片描述

4.设置监听器

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

在这里插入图片描述

5.再跟踪到run方法

然后再跟踪到run方法

在这里插入图片描述

    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类。

在这里插入图片描述

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启动过程中完成回调。

在这里插入图片描述

进入查看

在这里插入图片描述

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

生命周期和对应事件

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

在这里插入图片描述

生命周期对应事件
startingApplicationStartingEvent
environmentPreparedApplicationEnvironmentPreparedEvent
contextPreparedApplicationContextInitializedEvent
contextLoadedApplicationPreparedEvent
startedApplicationStartedEvent
runningApplicationReadyEvent
failedApplicationFailedEvent

ApplicationArguments

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

在这里插入图片描述

ConfigurableEnvironment

ConfigurableEnvironment

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

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

在这里插入图片描述

总结


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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Perley620

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值