简单叙述 Spring Boot 启动过程

文章目录

      • 1. 准备阶段:应用启动的入口
      • 2. 创建 SpringApplication 对象:开始启动工作
      • 3. 配置环境(Environment):识别开发环境与生产环境
      • 4. 启动监听器和初始化器:感知启动的关键事件
      • 5. 创建 ApplicationContext 容器:加载核心 Bean
      • 6. 自动配置(Auto-Configuration):自动加载所需 Bean
      • 7. 启动内嵌 Web 服务器:Tomcat、Jetty、Undertow
      • 8. 执行 CommandLineRunner 和 ApplicationRunner
      • 9. 启动完成:应用已准备好接收请求
      • 总结
      • 推荐阅读文章

Spring Boot 是一个帮助 Java 开发者快速搭建和启动应用的框架。了解它的启动过程,可以帮助我们深入理解 Spring Boot 的工作原理,尤其是它如何将配置、组件扫描、自动配置等内容串联起来。我们用一个直观的流程来解读 Spring Boot 的启动过程。

1. 准备阶段:应用启动的入口

Spring Boot 应用程序的启动通常从一个 main 方法开始(在 Application 类中)。这个 main 方法会调用 SpringApplication.run(Application.class, args),其实就是从这一步开始启动整个应用。

流程描述

  • 你可以把 SpringApplication.run() 理解为一个“开关”,它会启动一连串的动作。
  • 一旦调用 run(),Spring Boot 就会进入自动化启动的“准备阶段”。

2. 创建 SpringApplication 对象:开始启动工作

SpringApplication.run() 会首先创建一个 SpringApplication 对象。这个对象可以看作是启动应用的“总指挥”,主要负责:

  • 设置应用的环境(Environment),比如是否是开发环境、生产环境等。
  • 加载初步配置。
  • 为后续的步骤做准备工作,比如准备监听器、事件发布等。

小贴士:在这个阶段,Spring Boot 会检查一些常见的配置文件(如 application.propertiesapplication.yml),并准备将这些配置信息应用到启动流程中。

3. 配置环境(Environment):识别开发环境与生产环境

Spring Boot 的 SpringApplication 对象会进一步去配置环境。比如,通过读取配置文件或者系统属性,它能识别应用当前是在开发环境还是生产环境,并根据不同环境做适当的优化。

案例

  • 假设你在 application.yml 中配置了 spring.profiles.active=dev,Spring Boot 会加载适用于 dev 环境的配置。
  • 这种分环境的配置机制,让应用在开发和生产之间可以无缝切换。

4. 启动监听器和初始化器:感知启动的关键事件

Spring Boot 启动过程中,还会初始化一些监听器(Listeners)和初始化器(Initializers)。它们的作用是“监听”启动过程中的各个步骤,并在关键时刻触发特定的逻辑。

案例

  • 你可以注册一个监听器,在 Spring Boot 启动时触发一些定制的行为,比如打印系统信息、记录日志等。

效果

  • 这种机制帮助开发者对启动过程拥有更高的可控性,也可以在启动时执行一些初始化工作。

5. 创建 ApplicationContext 容器:加载核心 Bean

这个步骤中,Spring Boot 会启动 ApplicationContext(应用上下文),它可以理解为一个容器,负责管理应用中的所有 Bean。

加载过程

  • ApplicationContext 会扫描项目中被 @Component@Service@Repository 等注解标记的类,把它们注册为 Bean。
  • Spring Boot 还会根据自动配置(Auto-Configuration),加载额外的 Bean。比如,发现项目里有数据库依赖时,自动配置会加载数据库连接池的相关 Bean。

案例

  • 当你用 @SpringBootApplication 注解启动项目时,自动配置会根据类路径下的依赖,比如 spring-boot-starter-web,帮你自动加载 Web 服务器的相关配置和 Bean。

6. 自动配置(Auto-Configuration):自动加载所需 Bean

自动配置是 Spring Boot 启动的核心亮点。Spring Boot 会检测项目中的依赖项,并根据依赖,自动加载对应的配置。比如:

  • 如果有 Web 相关的依赖(如 spring-boot-starter-web),Spring Boot 会自动配置一个内嵌的 Tomcat 服务器。
  • 如果项目中有数据库相关的依赖(如 spring-boot-starter-data-jpa),它会自动加载数据源、事务管理等 Bean。

案例

  • 假设项目中添加了一个 Redis 依赖(如 spring-boot-starter-data-redis),Spring Boot 会自动配置 Redis 连接池、RedisTemplate 等 Bean,免去了手动配置的麻烦。

7. 启动内嵌 Web 服务器:Tomcat、Jetty、Undertow

如果你的项目是一个 Web 项目(包含 Web 依赖),Spring Boot 会启动一个内嵌的 Web 服务器,比如 Tomcat。这个步骤会绑定端口(默认是 8080),并启动一个 Web 服务,准备接收 HTTP 请求。

效果

  • Spring Boot 的内嵌服务器特性,让我们无需安装和配置外部服务器,这也是 Spring Boot 应用可以直接运行的原因之一。

8. 执行 CommandLineRunner 和 ApplicationRunner

在 Spring Boot 的启动流程最后,如果项目里实现了 CommandLineRunnerApplicationRunner 接口的 Bean,那么这些 Bean 的 run() 方法会被调用,执行启动后的收尾工作。

案例

  • 例如,你可以实现一个 CommandLineRunner,在项目启动完成后执行一些初始化操作,比如从数据库加载默认数据,或检查系统状态等。

9. 启动完成:应用已准备好接收请求

到这里,Spring Boot 的启动流程基本完成。你的应用已经启动,所有配置已加载、Bean 已注册,服务也在监听端口等待请求。整个启动过程就是一个自动化和配置化的过程,让你专注业务代码,而不需要为每个 Bean、每个组件的配置费心。


总结

Spring Boot 的启动过程可以理解为九个关键步骤:

  1. 启动入口:调用 SpringApplication.run(),启动流程。
  2. 创建 SpringApplication 对象:做启动前的准备。
  3. 配置环境:识别开发环境与生产环境。
  4. 启动监听器和初始化器:处理关键事件。
  5. 创建 ApplicationContext 容器:加载 Bean。
  6. 自动配置:根据依赖自动加载相关配置。
  7. 启动 Web 服务器:若是 Web 项目,启动内嵌服务器。
  8. 执行 CommandLineRunner / ApplicationRunner:启动后执行收尾工作。
  9. 启动完成:应用准备好,开始接收请求。

Spring Boot 的启动过程充分展示了其“约定优于配置”的理念,极大简化了 Java 项目的启动流程。希望这篇文章能帮助你对 Spring Boot 的启动过程有更清晰的认识!

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

上一篇:图像处理实验二(Image Understanding and Basic Processing)


下一篇:集群聊天服务器(2)Json介绍-Json序列化