Skip to content

SpringApplication

SpringApplication 类提供了一种便捷的方式来引导从 main() 方法启动的 Spring 应用程序。在许多情况下,你可以直接委托给静态的 SpringApplication.run(Class, String...) 方法:

java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

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

}
kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
	runApplication<MyApplication>(*args)
}

1. 启动失败处理 (Startup Failure)

如果你的应用程序启动失败,注册的 FailureAnalyzer 豆(Beans)会尝试提供专门的错误消息和具体的修复操作建议。例如,如果端口被占用:

text
***************************
APPLICATION FAILED TO START
***************************

Description:
Embedded servlet container failed to start. Port 8080 was already in use.

Action:
Identify and stop the process that is listening on port 8080 or configure this application to listen on another port.

::: note 注意 Spring Boot 提供了许多内置的 FailureAnalyzer 实现,你也可以添加自己的实现。 :::

2. 延迟初始化 (Lazy Initialization)

开启延迟初始化后,Bean 将在需要时创建,而不是在启动时创建。这可以缩短启动时间,但在 Web 应用中可能导致首个请求变慢。

  • 开启方式
    • 代码:application.setLazyInitialization(true)
    • 配置:spring.main.lazy-initialization=true

提示

如果你想对特定 Bean 禁用延迟加载,可以使用 @Lazy(false)

3. 自定义 Banner

在类路径下创建 banner.txt 即可自定义启动图案。支持以下占位符:

  • ${application.version}: 声明在 MANIFEST.MF 中的版本。
  • ${spring-boot.version}: 正在使用的 Spring Boot 版本。
  • ${AnsiColor.NAME}: ANSI 颜色转义码。

提示

使用 spring.main.banner-mode=off 可以禁用 Banner 打印。

4. 自定义 SpringApplication

如果默认配置不符合需求,可以手动实例化并配置:

java
public static void main(String[] args) {
	SpringApplication application = new SpringApplication(MyApplication.class);
	application.setBannerMode(Banner.Mode.OFF);
	application.run(args);
}

5. 流式构建 API (Fluent Builder API)

如果你需要构建 ApplicationContext 层次结构(父子上下文),可以使用 SpringApplicationBuilder

java
new SpringApplicationBuilder()
	.sources(Parent.class)
	.child(Application.class)
	.bannerMode(Banner.Mode.OFF)
	.run(args);

6. 应用程序可用性 (Application Availability)

Spring Boot 内置支持 存活状态 (Liveness)就绪状态 (Readiness),常用于 Kubernetes 探针。

  • Liveness State: 应用内部状态是否允许其正常工作(失败时是否需要重启)。
  • Readiness State: 应用是否准备好处理流量。
  • 管理状态: 你可以注入 ApplicationAvailability 来查询状态,或通过 AvailabilityChangeEvent 发布状态变更。

7. 应用程序事件与监听器

事件按以下顺序发送:

  1. ApplicationStartingEvent: 运行开始,除监听器注册外。
  2. ApplicationEnvironmentPreparedEvent: 环境已准备好,但上下文尚未创建。
  3. ApplicationContextInitializedEvent: 上下文已准备好,初始化器已调用。
  4. ApplicationPreparedEvent: 上下文刷新前,Bean 定义已加载。
  5. ApplicationStartedEvent: 上下文已刷新,但 Runner 尚未调用。
  6. AvailabilityChangeEvent (LivenessState.CORRECT): 应用被标记为存活。
  7. ApplicationReadyEvent: Runner 已调用。
  8. AvailabilityChangeEvent (ReadinessState.ACCEPTING_TRAFFIC): 应用已准备好接收请求。
  9. ApplicationFailedEvent: 启动异常。

8. Web 环境 (Web Environment)

SpringApplication 会自动探测应用类型:

  • 存在 Spring MVC -> AnnotationConfigServletWebServerApplicationContext
  • 仅存在 Spring WebFlux -> AnnotationConfigReactiveWebServerApplicationContext
  • 不存在 Web 库 -> AnnotationConfigApplicationContext

9. 访问应用程序参数

可以注入 ApplicationArguments 来获取传递给 main 方法的原始及解析后的参数。

10. 使用 Runner (ApplicationRunner / CommandLineRunner)

如果你需要在启动完成后运行逻辑,请实现其中之一。多个 Runner 可以通过 @Order 排序。

11. 退出处理 (Application Exit)

每个 SpringApplication 都会向 JVM 注册一个关闭钩子。你可以实现 ExitCodeGenerator 来在应用关闭时返回特定的退出码,并通过 System.exit() 传给操作系统。

12. 系统管理特性 (Admin Features)

通过 spring.application.admin.enabled 可以开启 JMX 管理,允许远程管理应用。

13. 启动过程追踪 (Startup Tracking)

使用 ApplicationStartup 可以追踪启动过程中的各步骤耗时(如 BufferingApplicationStartupFlightRecorderApplicationStartup)。

14. 虚拟线程 (Virtual Threads)

需 Java 21+。设置 spring.threads.virtual.enabled=true 启用。

  • 注意: 即使全员虚拟线程,也要防止 JVM 过早关闭,建议设置 spring.main.keep-alive=true

补充教学

1. 启动事件监听的陷阱

某些事件(如 ApplicationStartingEvent)在 ApplicationContext 创建之前就已发布,因此不能通过 @Bean@EventListener 在 Spring 容器中注册。 解决办法:在 META-INF/spring.factories 中配置,或者使用 application.addListeners(...)

2. Liveness 与 Readiness 的本质区别

  • 存活探针 (Liveness):如果它失败,K8s 会杀掉并重启容器。适用于应用进入死锁或内存溢出等无法自愈的场景。
  • 就绪探针 (Readiness):如果它失败,K8s 会从 Service 的负载均衡中移除该实例。适用于应用正在初始化大数据、或是依赖的外部中间件暂时不可用的场景。

3. 如何解决“虚拟线程”导致的守护进程退出?

虚拟线程默认是“守护线程”。如果应用中没有非守护线程在运行,JVM 会直接退出。在 Spring Boot 3.2+ 中,若开启虚拟线程且依赖调度任务维持运行,务必开启 spring.main.keep-alive=true,它会创建一个活跃的非守护线程保持程序存续。

Based on Spring Framework.