跟着AI学spring(一) SpringApplication.run

使用模型:通义灵码(阿里通义) Spring Boot框架中的核心启动方法 /** * 启动Spring应用程序,并返回一个配置化的应用程序上下文。 * * @param args 命令行参数,传递给Spring应用程序。 * @return Con

使用模型:通义灵码(阿里通义)

Spring Boot框架中的核心启动方法

    /**
     * 启动Spring应用程序,并返回一个配置化的应用程序上下文。
     * 
     * @param args 命令行参数,传递给Spring应用程序。
     * @return ConfigurableApplicationContext 可配置的应用程序上下文,提供了对应用程序生命周期的控制。
     */
public ConfigurableApplicationContext run(String... args) {
        // 注册关闭钩子,以便于在JVM关闭时执行特定的清理逻辑
        if (this.registerShutdownHook) {
            shutdownHook.enableShutdowHookAddition();
        }
        // 记录启动时间,用于计算启动耗时
        long startTime = System.nanoTime();
        // 创建引导上下文
        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);
            // 配置环境
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
            // 打印启动横幅
            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);
            // 调用自定义的运行器
            this.callRunners(context, applicationArguments);
        } catch (Throwable var12) {
            // 处理启动过程中抛出的异常
            if (var12 instanceof AbandonedRunException) {
                throw var12;
            }

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

        try {
            // 检查应用程序是否成功运行,如果运行成功,则通知监听器应用程序已准备就绪
            if (context.isRunning()) {
                Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
                listeners.ready(context, timeTakenToReady);
            }

            return context;
        } catch (Throwable var11) {
            // 处理运行就绪阶段抛出的异常
            if (var11 instanceof AbandonedRunException) {
                throw var11;
            } else {
                this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
                throw new IllegalStateException(var11);
            }
        }
    }

详细描述

该函数 run(String… args) 是Spring Boot框架中的核心启动方法,其功能是根据提供的参数(如命令行参数)初始化并启动一个Spring应用。以下是函数执行的详细步骤:

1、注册关闭钩子:如果配置了 registerShutdownHook 为 true,则启用关闭钩子。这使得当JVM正常退出(如通过 System.exit() 或终端发送的SIGTERM信号)时,Spring Boot应用能够进行资源清理等优雅关闭操作。关闭钩子由 shutdownHook.enableShutdowHookAddition() 方法实现。

2、记录启动时间:获取当前系统纳秒时间,作为计算启动耗时的起点。

3、创建引导上下文:调用 createBootstrapContext() 方法创建一个 DefaultBootstrapContext 实例,这是Spring Boot启动过程中的基础上下文,用于存储一些早期初始化所需的对象或信息。

4、初始化变量:将 ConfigurableApplicationContext 类型的变量 context 初始化为 null,用于后续存储创建的应用上下文。

5、配置无头属性:调用 configureHeadlessProperty() 方法,可能设置系统属性(如 java.awt.headless),以适应无图形界面(headless)环境。

6、获取运行监听器:调用 getRunListeners(args) 方法,根据提供的参数获取 SpringApplicationRunListeners 实例。这些监听器将在启动过程中接收通知,以便执行特定的生命周期回调。

7、触发监听器的 starting() 方法:使用创建的引导上下文和主应用类,调用所有运行监听器的 starting() 方法,通知它们Spring Boot应用启动流程开始。

8、创建应用参数:使用传入的 args 参数创建一个 DefaultApplicationArguments 实例,封装应用启动时的命令行参数。

9、准备环境:调用 prepareEnvironment() 方法,结合运行监听器、引导上下文、应用参数,创建并配置 ConfigurableEnvironment 实例,这是Spring应用的核心环境对象,包含各种系统属性、环境变量、配置信息等。

10、打印欢迎信息(Banner):调用 printBanner() 方法,根据配置和环境信息生成并打印Spring Boot应用的启动欢迎信息(通常是一段ASCII艺术和版本信息)。

11、创建应用上下文:调用 createApplicationContext() 方法,基于已准备好的环境创建 ConfigurableApplicationContext 实例,这是Spring应用的核心容器,用于管理Bean的生命周期、依赖注入等。

12、配置应用上下文:设置应用上下文的 applicationStartup 属性,用于监控应用启动过程中的性能指标。

13、准备上下文:调用 prepareContext() 方法,进一步配置应用上下文,包括加载应用的主类、处理配置文件、注册监听器等。

14、刷新上下文:调用 refreshContext() 方法,触发应用上下文的刷新流程。这是Spring IoC容器启动的关键步骤,包括Bean定义的解析、Bean的实例化、依赖注入、Bean的初始化等。

15、启动后处理:调用 afterRefresh() 方法,在应用上下文刷新完成后执行一些额外的启动后操作,如注册定时任务、执行特定的Bean方法等。

16、计算并记录启动耗时:计算从启动开始到现在的纳秒时间差,转换为 Duration 对象表示启动耗时。如果配置了 logStartupInfo 为 true,则通过 StartupInfoLogger.logStarted() 方法记录启动耗时及相关信息到日志中。

17、触发监听器的 started() 方法:使用计算出的启动耗时,调用所有运行监听器的 started() 方法,通知它们Spring Boot应用已成功启动。

18、调用自定义运行器:调用 callRunners() 方法,执行应用上下文中定义的 CommandLineRunnerApplicationRunner 接口实现类,这些类通常用于执行应用的特定初始化逻辑。

19、报告应用已准备就绪:若应用上下文仍在运行(未被关闭),计算从启动开始到现在的纳秒时间差,转换为 Duration 表示准备就绪耗时。触发监听器的 ready() 方法,通知它们Spring Boot应用已完全启动并准备就绪。

20、返回应用上下文:在所有步骤执行完毕且无异常抛出的情况下,返回创建的 ConfigurableApplicationContext 实例。这个上下文对象可以被外部代码用于访问和操作Spring应用。

异常处理
在整个启动过程中,函数会捕获并处理所有未被捕获的 Throwable 异常。对于 AbandonedRunException 类型的异常,直接重新抛出;其他类型的异常,则通过 handleRunFailure() 方法进行清理操作(如关闭已创建的应用上下文),然后包装成 IllegalStateException 抛出。这样确保即使在启动失败的情况下,也能进行必要的资源清理,并向外提供一致的异常信息。

LICENSED UNDER CC BY-NC-SA 4.0
Comment