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 可以追踪启动过程中的各步骤耗时(如 BufferingApplicationStartup 或 FlightRecorderApplicationStartup)。

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.