spring boot 2.7 项目启动流程

开发任何基于 Spring Boot 的项目,我们都会使用以下的启动类:
首先在idea中构建一个全新的springboot程序

大致的启动类长这样:

@SpringBootApplication
public class Demo1Application {

    public static void main(String[] args) {
        //1、new了一个SpringApplication对象,使用SPI技术加载spring.factories文件中ApplicationContextInitializer、ApplicationListener 接口实例
        //2.调用SpringApplication.run() 方法
        SpringApplication.run(Demo1Application.class, args);
    }

}

可以看到,Demo1Application 类中定义了注解 @SpringBootApplication,main 方法里通过 SpringApplication.run 来启动整个应用程序。因此要研究 Spring Boot 的启动原理,我们就需要从这两个地方入手。首先我们研究这个@SpringBootApplication这个注解,实际上这个注解是3个注解的联合,分别是

@SpringBootConfiguration 用于标识当前类是一个配置类,所以我们在启动类中也可以写入一些配置,其实就是一个 Configuration,但是 Spring Boot 推荐用 SpringBootConfiguration 来代替 Configuration。
@EnableAutoConfiguration  可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。
@ComponentScan   根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,可以通过 basePakcages 来指定其扫描的范围,如果不指定,则默认从标注了 @ComponentScan 注解的类所在包开始扫描。

每一个SpringBoot程序都有一个主入口,这个主入口就是main方法,而main方法中都会调用SpringBootApplication.run方法,一个快速了解SpringBootApplication启动过程的好方法就是在run方法中打一个断点,然后通过Debug的模式启动工程,逐步跟踪了解SpringBoot源码是如何完成环境准备和启动加载bean的。接下来我们跟着run方法研究他的执行流程,一直点击run方法,直到出现以下代码块

 public ConfigurableApplicationContext run(String... args) {
        //记录任务的执行时间
        long startTime = System.nanoTime();
         // 创建引导上下文
        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
         // 定义可配置的应用程序上下文变量
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
         // 获取运行监听器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
         // 启动监听器
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
             // 默认应用程序参数,将args封装为 ApplicationArguments 对象
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //接着prepareEnvironment根据运行监听器和参数准备spring环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            //接着调用createApplicationContext方法创建应用上下文
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            //通过prepareContext准备应用上下文
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            //调用refreshContext() 方法启动Spring容器和内置的Servlet容器
            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);
            //callRunners方法执行所有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);
        }
    }

最后我们来进行总结

  • 记录任务的执行时间

  • 创建引导上下文

  • 定义可配置的应用程序上下文变量

  • 获取运行监听器

  • 启动监听器

  • 默认应用程序参数,将args封装为 ApplicationArguments 对象

  • 接着prepareEnvironment根据运行监听器和参数准备spring环境

  • 接着调用createApplicationContext方法创建应用上下文

  • 通过prepareContext准备应用上下文

  • 调用refreshContext() 方法启动Spring容器和内置的Servlet容器

  • callRunners方法执行所有runner运行器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

''如果

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

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

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

打赏作者

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

抵扣说明:

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

余额充值