springboot 启动原理

发布时间:2023年12月28日

这里简单总结下 SpringBoot 项目的启动流程。

源码

入口

main() 方法中的 SpringApplication.run() 为整个 springboot 程序的主入口,即图一所示。
在这里插入图片描述

进入图一中的 run() 方法后可以看到程序会执行两个方法 SpringApplication() 和 run() 方法。
在这里插入图片描述

SpringApplication()

我们首先看一下 SpringApplication() 方法的执行流程
在这里插入图片描述
在创建SpringApplication对象的时候,在它的构造方法内部主要做3个事情。

  1. 确认web应用类型,一般情况下是servlet类型,这种类型的应用,将来会自动启动一个tomcat
  2. 从spring.factories配置文件中,加载默认的ApplicationContextlnitializer和ApplicationListener
  3. 记录当前应用的主启动类,将来做包扫描使用

run()

其次是 run() 方法,这里贴一下 run() 方法的源码,主要内容为 try 语句里面的内容。

public ConfigurableApplicationContext run(String... args) {
        SpringApplication.Startup startup = SpringApplication.Startup.create();
        if (this.registerShutdownHook) {
            shutdownHook.enableShutdownHookAddition();
        }

        DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
        ConfigurableApplicationContext context = null;
        this.configureHeadlessProperty();
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting(bootstrapContext, this.mainApplicationClass);

        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            // 准备 Environment 对象
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            // 打印 Banner ,即 springboot 的那个图标
            Banner printedBanner = this.printBanner(environment);
            // 实例化 IOC 容器
            context = this.createApplicationContext();
            context.setApplicationStartup(this.applicationStartup);
            // 准备容器,为容器设置 environment, BeanFactoryPostProcessot, 并加载主类对应的BeanDefinition。
            this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
            // 刷新容器,创建 Bean 实例
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            // 调用监听器
            startup.started();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), startup);
            }

            listeners.started(context, startup.timeTakenToStarted());
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            if (var10 instanceof SpringApplication.AbandonedRunException) {
                throw var10;
            }

            this.handleRunFailure(context, var10, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            if (context.isRunning()) {
                listeners.ready(context, startup.ready());
            }

            return context;
        } catch (Throwable var9) {
            if (var9 instanceof SpringApplication.AbandonedRunException) {
                throw var9;
            } else {
                this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null);
                throw new IllegalStateException(var9);
            }
        }
    }

源码流程总结

大体流程

总结

面试时,可以根据源码按照总分总的形式回答出下面的内容:
总结

文章来源:https://blog.csdn.net/weixin_46515691/article/details/135138692
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。