返回

Spring Boot 启动流程详解 - Launcher 类的奥秘

后端

深入剖析 Launcher 类:Spring Boot 启动机制的幕后英雄

Launcher 类的使命

Launcher 类 在 Spring Boot 应用程序启动过程中扮演着至关重要的角色。它负责创建一个 SpringApplication 实例,并调用其 run() 方法。run() 方法启动应用程序上下文,加载必要的 bean,并启动服务器。Launcher 类还负责处理命令行参数,允许你在启动应用程序时指定特定的配置。

Launcher 类的关键步骤

Launcher 类的启动流程包括以下关键步骤:

  1. 创建 SpringApplication 实例 :Launcher 类通过调用 SpringApplication.run() 方法创建 SpringApplication 实例。
  2. 设置应用程序的环境属性 :Launcher 类设置应用程序的环境属性,如应用程序的名称、配置文件的位置等。
  3. 准备应用程序上下文的运行环境 :Launcher 类准备应用程序上下文的运行环境,包括创建应用程序上下文的父上下文、设置应用程序上下文的 ClassLoader 等。
  4. 调用 SpringApplication 实例的 run() 方法 :Launcher 类调用 SpringApplication 实例的 run() 方法。run() 方法启动应用程序上下文,加载必要的 bean,并启动服务器。
  5. 加载应用程序上下文中的 bean :Launcher 类加载应用程序上下文中的 bean。bean 是 Spring 应用程序的基本构建块,它们代表应用程序中的各种组件和服务。
  6. 启动嵌入式服务器 :Launcher 类启动嵌入式服务器。嵌入式服务器是 Spring Boot 提供的内置服务器,它允许你无需单独部署服务器即可运行 Spring Boot 应用程序。

Launcher 类的详细介绍

1. 创建 SpringApplication 实例

Launcher 类通过调用 SpringApplication.run() 方法创建 SpringApplication 实例。该方法接收应用程序的主类和命令行参数作为参数。主类是一个包含 main() 方法的类,通常是应用程序的入口点。

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return new SpringApplication(primarySource).run(args);
}

2. 设置应用程序的环境属性

Launcher 类设置应用程序的环境属性,如应用程序的名称、配置文件的位置等。这些属性可以从命令行参数、系统属性或环境变量中获取。

protected Properties getProperties(String[] args) {
    Properties properties = new Properties();
    // 从命令行参数中获取属性
    CommandLinePropertySource argsProps = new CommandLinePropertySource(args);
    addProperties(properties, argsProps);
    // 从系统属性中获取属性
    SystemPropertySource systemProps = new SystemPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME);
    addProperties(properties, systemProps);
    // 从环境变量中获取属性
    EnvironmentPropertySource envProps = new EnvironmentPropertySource(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
            env);
    addProperties(properties, envProps);
    return properties;
}

3. 准备应用程序上下文的运行环境

Launcher 类准备应用程序上下文的运行环境,包括创建应用程序上下文的父上下文、设置应用程序上下文的 ClassLoader 等。

protected ConfigurableApplicationContext prepareContext(String[] args) {
    ApplicationContext parent = createParentContext();
    ConfigurableApplicationContext context = createApplicationContext();
    postProcessApplicationContext(context);
    // 设置应用程序上下文的父上下文
    context.setParent(parent);
    // 设置应用程序上下文的 ClassLoader
    context.setClassLoader(getClassLoader());
    return context;
}

4. 调用 SpringApplication 实例的 run() 方法

Launcher 类调用 SpringApplication 实例的 run() 方法。run() 方法启动应用程序上下文,加载必要的 bean,并启动服务器。

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
            new Class[]{ClassLoader.class}, getBeanClassLoader());
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 启动应用程序上下文
        ConfigurableApplicationContext parent = prepareContext(args);
        context = run(parent, applicationArguments, new SimpleCommandLinePropertySource(args));
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, stopWatch);
        throw new IllegalStateException(ex);
    }
    try {
        afterRun(context, applicationArguments, stopWatch);
    }
    catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, stopWatch);
        throw new IllegalStateException(ex);
    }
    return context;
}

5. 加载应用程序上下文中的 bean

Launcher 类加载应用程序上下文中的 bean。bean 是 Spring 应用程序的基本构建块,它们代表应用程序中的各种组件和服务。bean 可以通过注解、XML 配置或 Java 代码来定义。

protected ConfigurableApplicationContext run(ConfigurableApplicationContext parent, ApplicationArguments args,
                                              PropertySource<?> propertySource) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext applicationContext;
    try {
        // 加载应用程序上下文中的 bean
        applicationContext = refreshContext(parent, args, propertySource);
    }
    catch (Throwable ex) {
        handleRunFailure(applicationContext, ex, getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                new Class[]{ClassLoader.class}, getBeanClassLoader()), stopWatch);
        throw new IllegalStateException(ex);
    }
    try {
        afterRefresh(applicationContext, args, stopWatch);
    }
    catch (Throwable ex) {
        handleRunFailure(applicationContext, ex, getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                new Class[]{ClassLoader.class}, getBeanClassLoader()), stopWatch);
        throw new IllegalStateException(ex);
    }
    return applicationContext;
}

6. 启动嵌入式服务器

Launcher 类启动嵌入式服务器。嵌入式服务器是 Spring Boot 提供的内置服务器,它允许你无需单独部署服务器即可运行 Spring Boot 应用程序。

protected void afterRefresh(ConfigurableApplicationContext context, ApplicationArguments args, StopWatch stopWatch) {
    callRunners(context, args);
    // 启动嵌入式服务器
    WebServer webServer = this.webApplicationType.getWebServer(context);
    webServer.start();
    int port = webServer.getPort();
    context.publishEvent(new ServletWebServerInitializedEvent(webServer, port, context.getServletContext()));
}

Launcher 类的实战应用

Launcher 类在 Spring Boot 应用程序中有着广泛的应用。以下是一些常见的应用场景:

  • 指定应用程序的配置文件。
  • 启用或禁用特定的 bean。
  • 设置应用程序的端口号。
  • 运行应用程序的测试用例。

总结

Launcher 类是 Spring Boot 启动流程的核心组件之一。它负责创建 SpringApplication 实例,设置应用程序的环境属性,准备应用程序上下文的运行环境,调用 SpringApplication 实例的 run() 方法,加载应用程序上下文中的 bean,并启动嵌入式服务器。通过理解 Launcher 类的启动流程,你可以更深入地理解 Spring Boot 的启动机制,并能够更加熟练地使用 Spring Boot 开发应用程序。

常见问题解答

  1. Launcher 类何时创建?
    Launcher 类在 Spring Boot 应用程序的 main() 方法中创建。
  2. Launcher 类如何与 SpringApplication 类的 run() 方法交互?
    Launcher 类创建 SpringApplication 实例并调用其 run() 方法来启动应用程序。
  3. Launcher 类如何设置应用程序的环境属性?
    Launcher 类从命令行参数、系统属性和环境变量中获取应用程序的环境属性。
  4. Launcher 类如何准备应用程序上下文的运行环境?
    Launcher 类创建应用程序上下文的父上下文、设置应用程序上下文的 ClassLoader 等来准备应用程序上下文的运行环境。
  5. Launcher 类如何启动嵌入式服务器?
    Launcher 类通过调用 getWebServer() 方法获取嵌入式服务器并将其启动。