【SpringBoot】深入剖析 Spring Boot 启动过程(附源码与实战)

发布于:2025-03-12 ⋅ 阅读:(16) ⋅ 点赞:(0)

深入剖析 Spring Boot 启动过程(附源码与实战)

Spring Boot 以其“开箱即用”的特性深受开发者喜爱,然而,Spring Boot 是如何启动的?它如何做到自动化配置?这背后的原理是什么?本篇文章将从源码出发,剖析 Spring Boot 启动的核心流程,并通过代码实战加深理解。


1. Spring Boot 启动的核心流程

Spring Boot 应用的启动通常从 main 方法开始,例如:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

其中 SpringApplication.run() 是启动的关键入口,我们接下来深入分析其核心流程。

1.1 SpringApplication.run() 过程

源码入口位于 SpringApplication 类的 run() 方法:

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

它主要做了如下几件事:

  1. 创建 SpringApplication 实例
  2. 调用 run() 方法,执行核心启动逻辑
  3. 返回 ConfigurableApplicationContext 作为 Spring 容器

进一步分析 run() 方法内部逻辑:

public ConfigurableApplicationContext run(String... args) {
    long startTime = System.nanoTime();

    // 1. 创建并启动 `SpringApplicationRunListeners`
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();

    // 2. 构造 `ApplicationArguments`
    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

    // 3. 准备 `Environment`
    ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);

    // 4. 打印 Banner
    printBanner(environment);

    // 5. 创建 `ApplicationContext`
    ConfigurableApplicationContext context = createApplicationContext();

    // 6. 准备 `ApplicationContext`
    prepareContext(context, environment, listeners, applicationArguments);

    // 7. 刷新 `ApplicationContext`
    refreshContext(context);

    // 8. 执行 `ApplicationRunner` 和 `CommandLineRunner`
    afterRefresh(context, applicationArguments);

    // 9. 通知所有监听器,启动完成
    listeners.started(context);
    listeners.running(context);

    return context;
}

1.2 关键步骤详解

1️⃣ SpringApplicationRunListeners

getRunListeners(args) 方法中,会加载 META-INF/spring.factories 中的 SpringApplicationRunListener,如 EventPublishingRunListener,用于发布 Spring Boot 启动相关的事件,如 ApplicationStartedEvent

2️⃣ Environment 准备

prepareEnvironment() 方法用于加载 application.propertiesapplication.yml 等配置信息,并决定是否启用 DevTools

3️⃣ 创建 Spring 容器

createApplicationContext() 通过 SpringFactoriesLoader 加载 SpringApplication 配置的 ApplicationContext 实现类(如 AnnotationConfigServletWebServerApplicationContext),然后 prepareContext() 进行配置。

4️⃣ 刷新容器

refreshContext() 最终调用 context.refresh(),完成 Spring 核心的 refresh() 过程,初始化 BeanFactory,注册 Bean 后处理器,完成 AOP、事务等功能的初始化。

5️⃣ 运行 ApplicationRunnerCommandLineRunner

Spring Boot 提供 ApplicationRunnerCommandLineRunner 接口,在 afterRefresh() 方法中执行,可以在应用启动后运行特定代码:

@Component
public class MyRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("ApplicationRunner 执行,参数:" + Arrays.toString(args.getSourceArgs()));
    }
}

2. 代码实战:自定义 SpringApplicationRunListener

我们可以自定义 SpringApplicationRunListener 来监听 Spring Boot 启动过程,并记录日志。

2.1 创建 MyApplicationRunListener

public class MyApplicationRunListener implements SpringApplicationRunListener {

    public MyApplicationRunListener(SpringApplication application, String[] args) {}

    @Override
    public void starting() {
        System.out.println(">>> Spring Boot 正在启动...");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        System.out.println(">>> Environment 已准备:" + environment.getActiveProfiles());
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println(">>> ApplicationContext 已创建...");
    }

    @Override
    public void started(ConfigurableApplicationContext context) {
        System.out.println(">>> Spring Boot 已启动!");
    }

    @Override
    public void running(ConfigurableApplicationContext context) {
        System.out.println(">>> Spring Boot 运行中...");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println(">>> 启动失败:" + exception.getMessage());
    }
}

2.2 配置 META-INF/spring.factories

resources/META-INF/spring.factories 文件中,添加:

org.springframework.boot.SpringApplicationRunListener=com.example.listener.MyApplicationRunListener

这样,Spring Boot 启动时,就会自动加载 MyApplicationRunListener,输出日志。


3. 总结

  1. Spring Boot 启动的核心入口是 SpringApplication.run(),它完成环境准备、容器创建、事件发布等步骤。
  2. 核心组件包括 SpringApplicationRunListenersEnvironmentApplicationContext,它们协同完成应用初始化。
  3. 我们可以自定义 SpringApplicationRunListener,监听 Spring Boot 启动事件,实现日志记录或其他增强功能。

Spring Boot 的启动过程是一个标准化的“模板方法模式”实现,每一步都可以通过扩展点进行自定义,极大增强了框架的可扩展性。希望本篇文章能帮助你更好地理解 Spring Boot 的启动原理!


📌 你学会了吗? 欢迎在评论区留言交流!🚀