此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.3.1

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.3.1

该类提供了一种方便的方法来引导从方法启动的 Spring 应用程序。 在许多情况下,可以委托给静态方法,如以下示例所示:SpringApplicationmain()SpringApplication.run

  • Java

  • Kotlin

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);
	}

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


@SpringBootApplication
class MyApplication

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

应用程序启动时,应会看到类似于以下输出的内容:When your application starts, you should see something similar to the following output:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/

 :: Spring Boot ::       (v3.3.2-SNAPSHOT)

2024-06-22T03:35:31.731Z  INFO 81452 --- [           main] o.s.b.d.f.logexample.MyApplication       : Starting MyApplication using Java 17.0.11 with PID 81452 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
2024-06-22T03:35:31.735Z  INFO 81452 --- [           main] o.s.b.d.f.logexample.MyApplication       : No active profile set, falling back to 1 default profile: "default"
2024-06-22T03:35:34.337Z  INFO 81452 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2024-06-22T03:35:34.383Z  INFO 81452 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-06-22T03:35:34.386Z  INFO 81452 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.25]
2024-06-22T03:35:34.503Z  INFO 81452 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-06-22T03:35:34.506Z  INFO 81452 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2576 ms
2024-06-22T03:35:35.756Z  INFO 81452 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2024-06-22T03:35:35.789Z  INFO 81452 --- [           main] o.s.b.d.f.logexample.MyApplication       : Started MyApplication in 5.407 seconds (process running for 6.479)

默认情况下,将显示日志记录消息,包括一些相关的启动详细信息,例如启动应用程序的用户。 如果需要 以外的日志级别,可以设置它,如日志级别中所述。 应用程序版本是使用主应用程序类包中的实现版本确定的。 可以通过设置为 来关闭启动信息日志记录。 这也将关闭应用程序的活动配置文件的日志记录。INFOINFOspring.main.log-startup-infofalse

若要在启动期间添加其他日志记录,可以在 的子类中重写。logStartupInfo(boolean)SpringApplication
若要在启动期间添加其他日志记录,可以在 的子类中重写。logStartupInfo(boolean)SpringApplication

启动失败

如果您的应用程序无法启动,则注册者有机会提供专用错误消息和解决问题的具体操作。 例如,如果在端口上启动 Web 应用程序,并且该端口已在使用中,则应看到类似于以下消息的内容:FailureAnalyzers8080

***************************
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.
Spring Boot 提供了许多实现,您可以添加自己的实现。FailureAnalyzer

如果没有故障分析器能够处理异常,您仍然可以显示完整的条件报告,以更好地了解出了什么问题。 为此,您需要启用 debug 属性启用 DEBUG 日志记录org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

例如,如果使用 运行应用程序,则可以启用该属性,如下所示:java -jardebug

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug
Spring Boot 提供了许多实现,您可以添加自己的实现。FailureAnalyzer

延迟初始化

SpringApplication允许延迟初始化应用程序。 启用延迟初始化后,将根据需要创建 Bean,而不是在应用程序启动期间创建。 因此,启用延迟初始化可以减少应用程序启动所需的时间。 在 Web 应用程序中,启用延迟初始化将导致许多与 Web 相关的 Bean 在收到 HTTP 请求之前不会被初始化。

延迟初始化的缺点是它可能会延迟发现应用程序的问题。 如果延迟初始化配置错误的 Bean,则在启动期间将不再发生故障,并且只有在初始化 Bean 时问题才会变得明显。 还必须注意确保 JVM 有足够的内存来容纳应用程序的所有 Bean,而不仅仅是那些在启动期间初始化的 Bean。 由于这些原因,缺省情况下不启用延迟初始化,建议在启用延迟初始化之前对 JVM 的堆大小进行微调。

可以使用 on 方法或 on 方法以编程方式启用延迟初始化。 或者,可以使用以下示例中所示的属性来启用它:lazyInitializationSpringApplicationBuildersetLazyInitializationSpringApplicationspring.main.lazy-initialization

  • Properties

  • YAML

spring.main.lazy-initialization=true
spring:
  main:
    lazy-initialization: true
如果要禁用某些 Bean 的延迟初始化,同时对应用程序的其余部分使用延迟初始化,则可以使用注释将其 lazy 属性显式设置为 false。@Lazy(false)
如果要禁用某些 Bean 的延迟初始化,同时对应用程序的其余部分使用延迟初始化,则可以使用注释将其 lazy 属性显式设置为 false。@Lazy(false)

自定义横幅

可以通过将文件添加到类路径或将属性设置为此类文件的位置来更改启动时打印的横幅。 如果文件的编码不是 UTF-8,则可以设置 .banner.txtspring.banner.locationspring.banner.charset

在文件中,可以使用 以及以下任何占位符中可用的任何键:banner.txtEnvironment

表 1.横幅变量
变量 描述

${application.version}

应用程序的版本号,如 中声明的。 例如,打印为 .MANIFEST.MFImplementation-Version: 1.01.0

${application.formatted-version}

应用程序的版本号,在 中声明并设置了显示格式(用括号括起来,并以 为前缀)。 例如。MANIFEST.MFv(v1.0)

${spring-boot.version}

您正在使用的 Spring Boot 版本。 例如。3.3.2-SNAPSHOT

${spring-boot.formatted-version}

您正在使用的 Spring Boot 版本,格式化为显示(用括号括起来,并以 为前缀)。 例如。v(v3.3.2-SNAPSHOT)

${Ansi.NAME}(或 , ,${AnsiColor.NAME}${AnsiBackground.NAME}${AnsiStyle.NAME})

其中是 ANSI 转义代码的名称。 有关详细信息,请参阅 AnsiPropertySourceNAME

${application.title}

应用程序的标题,如 中所述。 例如,打印为 .MANIFEST.MFImplementation-Title: MyAppMyApp

如果要以编程方式生成横幅,则可以使用该方法。 使用接口并实现自己的方法。SpringApplication.setBanner(…​)org.springframework.boot.BannerprintBanner()

您还可以使用该属性来确定横幅是否必须在 () 上打印、发送到配置的记录器 () 或根本不生成 ()。spring.main.banner-modeSystem.outconsolelogoff

打印的横幅注册为单例 Bean,其名称如下:。springBootBanner

仅当使用 Spring Boot 启动器或与 Spring Boot 启动器一起使用时, 、 和 属性才可用。 如果您正在运行解压缩的 jar 并启动它或将应用程序作为本机映像运行,则不会解析这些值。application.titleapplication.versionapplication.formatted-versionjava -jarjava -cpjava -cp <classpath> <mainclass>

要使用这些属性,请使用 java -jar 将应用程序作为打包的 jar 启动,或使用 java org.springframework.boot.loader.launch.JarLauncher 作为解压缩的 jar 启动。 这将初始化应用程序。横幅属性,然后再构建类路径并启动应用。application.

表 1.横幅变量
变量 描述

${application.version}

应用程序的版本号,如 中声明的。 例如,打印为 .MANIFEST.MFImplementation-Version: 1.01.0

${application.formatted-version}

应用程序的版本号,在 中声明并设置了显示格式(用括号括起来,并以 为前缀)。 例如。MANIFEST.MFv(v1.0)

${spring-boot.version}

您正在使用的 Spring Boot 版本。 例如。3.3.2-SNAPSHOT

${spring-boot.formatted-version}

您正在使用的 Spring Boot 版本,格式化为显示(用括号括起来,并以 为前缀)。 例如。v(v3.3.2-SNAPSHOT)

${Ansi.NAME}(或 , ,${AnsiColor.NAME}${AnsiBackground.NAME}${AnsiStyle.NAME})

其中是 ANSI 转义代码的名称。 有关详细信息,请参阅 AnsiPropertySourceNAME

${application.title}

应用程序的标题,如 中所述。 例如,打印为 .MANIFEST.MFImplementation-Title: MyAppMyApp

如果要以编程方式生成横幅,则可以使用该方法。 使用接口并实现自己的方法。SpringApplication.setBanner(…​)org.springframework.boot.BannerprintBanner()

仅当使用 Spring Boot 启动器或与 Spring Boot 启动器一起使用时, 、 和 属性才可用。 如果您正在运行解压缩的 jar 并启动它或将应用程序作为本机映像运行,则不会解析这些值。application.titleapplication.versionapplication.formatted-versionjava -jarjava -cpjava -cp <classpath> <mainclass>

要使用这些属性,请使用 java -jar 将应用程序作为打包的 jar 启动,或使用 java org.springframework.boot.loader.launch.JarLauncher 作为解压缩的 jar 启动。 这将初始化应用程序。横幅属性,然后再构建类路径并启动应用。application.

自定义 SpringApplication

如果默认值不符合您的口味,您可以改为创建本地实例并对其进行自定义。 例如,要关闭横幅,您可以编写:SpringApplication

  • Java

  • Kotlin

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

@SpringBootApplication
public class MyApplication {

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

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

@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
	runApplication<MyApplication>(*args) {
		setBannerMode(Banner.Mode.OFF)
	}
}
传递给的构造函数参数是 Spring Bean 的配置源。 在大多数情况下,这些是对类的引用,但它们也可以是直接引用类。SpringApplication@Configuration@Component

也可以使用文件进行配置。 有关详细信息,请参阅外部化配置SpringApplicationapplication.properties

有关配置选项的完整列表,请参阅 SpringApplication Javadoc

传递给的构造函数参数是 Spring Bean 的配置源。 在大多数情况下,这些是对类的引用,但它们也可以是直接引用类。SpringApplication@Configuration@Component

Fluent Builder API

如果您需要构建层次结构(具有父/子关系的多个上下文),或者如果您更喜欢使用“流畅”构建器 API,则可以使用 .ApplicationContextSpringApplicationBuilder

允许您将多个方法调用和 include 链接在一起,以及允许您创建层次结构的方法,如以下示例所示:SpringApplicationBuilderparentchild

  • Java

  • Kotlin

		new SpringApplicationBuilder().sources(Parent.class)
			.child(Application.class)
			.bannerMode(Banner.Mode.OFF)
			.run(args);
		SpringApplicationBuilder()
			.sources(Parent::class.java)
			.child(Application::class.java)
			.bannerMode(Banner.Mode.OFF)
			.run(*args)
创建层次结构时存在一些限制。 例如,Web 组件必须包含在子上下文中,并且父上下文和子上下文都使用相同的组件。 有关完整的详细信息,请参见 SpringApplicationBuilder JavadocApplicationContextEnvironment
创建层次结构时存在一些限制。 例如,Web 组件必须包含在子上下文中,并且父上下文和子上下文都使用相同的组件。 有关完整的详细信息,请参见 SpringApplicationBuilder JavadocApplicationContextEnvironment

应用程序可用性

在平台上部署时,应用程序可以使用 Kubernetes Probes 等基础结构向平台提供有关其可用性的信息。 Spring Boot 包括对常用的“活动”和“就绪”可用性状态的开箱即用支持。 如果使用 Spring Boot 的“执行器”支持,则这些状态将公开为运行状况终结点组。

此外,您还可以通过将接口注入到您自己的 Bean 中来获取可用性状态。ApplicationAvailability

活体状态

应用程序的“活动”状态告诉其内部状态是否允许它正常工作,或者如果它当前失败,则自行恢复。 损坏的“活动”状态意味着应用程序处于无法从中恢复的状态,基础结构应重新启动应用程序。

通常,“活动”状态不应基于外部检查,例如运行状况检查。 如果是这样,则出现故障的外部系统(数据库、Web API、外部缓存)将触发整个平台的大规模重启和级联故障。

Spring Boot 应用程序的内部状态主要由 Spring 表示。 如果应用程序上下文已成功启动,则 Spring Boot 假定应用程序处于有效状态。 刷新上下文后,应用程序将被视为活动状态,请参阅 Spring Boot 应用程序生命周期和相关应用程序事件ApplicationContext

就绪状态

应用程序的“就绪”状态指示应用程序是否已准备好处理流量。 失败的“就绪”状态告诉平台,它目前不应将流量路由到应用程序。 这通常发生在启动期间、处理组件期间,或者如果应用程序认为它太忙而无法增加流量,则随时发生。CommandLineRunnerApplicationRunner

调用应用程序和命令行运行器后,应用程序就被视为准备就绪,请参阅 Spring Boot 应用程序生命周期和相关应用程序事件

预期在启动期间运行的任务应由 和 组件执行,而不是使用 Spring 组件生命周期回调,例如 。CommandLineRunnerApplicationRunner@PostConstruct

管理应用程序可用性状态

应用程序组件可以随时检索当前可用性状态,方法是注入接口并在其上调用方法。 更常见的是,应用程序需要侦听状态更新或更新应用程序的状态。ApplicationAvailability

例如,我们可以将应用程序的 “Readiness” 状态导出到一个文件中,以便 Kubernetes 的 “exec Probe” 可以查看此文件:

  • Java

  • Kotlin

import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.ReadinessState;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class MyReadinessStateExporter {

	@EventListener
	public void onStateChange(AvailabilityChangeEvent<ReadinessState> event) {
		switch (event.getState()) {
			case ACCEPTING_TRAFFIC -> {
				// create file /tmp/healthy
			}
			case REFUSING_TRAFFIC -> {
				// remove file /tmp/healthy
			}
		}
	}

}
import org.springframework.boot.availability.AvailabilityChangeEvent
import org.springframework.boot.availability.ReadinessState
import org.springframework.context.event.EventListener
import org.springframework.stereotype.Component

@Component
class MyReadinessStateExporter {

	@EventListener
	fun onStateChange(event: AvailabilityChangeEvent<ReadinessState?>) {
		when (event.state) {
			ReadinessState.ACCEPTING_TRAFFIC -> {
				// create file /tmp/healthy
			}
			ReadinessState.REFUSING_TRAFFIC -> {
				// remove file /tmp/healthy
			}
			else -> {
				// ...
			}
		}
	}

}

当应用程序中断且无法恢复时,我们还可以更新应用程序的状态:

  • Java

  • Kotlin

import org.springframework.boot.availability.AvailabilityChangeEvent;
import org.springframework.boot.availability.LivenessState;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

@Component
public class MyLocalCacheVerifier {

	private final ApplicationEventPublisher eventPublisher;

	public MyLocalCacheVerifier(ApplicationEventPublisher eventPublisher) {
		this.eventPublisher = eventPublisher;
	}

	public void checkLocalCache() {
		try {
			// ...
		}
		catch (CacheCompletelyBrokenException ex) {
			AvailabilityChangeEvent.publish(this.eventPublisher, ex, LivenessState.BROKEN);
		}
	}

}
import org.springframework.boot.availability.AvailabilityChangeEvent
import org.springframework.boot.availability.LivenessState
import org.springframework.context.ApplicationEventPublisher
import org.springframework.stereotype.Component

@Component
class MyLocalCacheVerifier(private val eventPublisher: ApplicationEventPublisher) {

	fun checkLocalCache() {
		try {
			// ...
		} catch (ex: CacheCompletelyBrokenException) {
			AvailabilityChangeEvent.publish(eventPublisher, ex, LivenessState.BROKEN)
		}
	}

}
通常,“活动”状态不应基于外部检查,例如运行状况检查。 如果是这样,则出现故障的外部系统(数据库、Web API、外部缓存)将触发整个平台的大规模重启和级联故障。
预期在启动期间运行的任务应由 和 组件执行,而不是使用 Spring 组件生命周期回调,例如 。CommandLineRunnerApplicationRunner@PostConstruct

应用程序事件和侦听器

除了通常的 Spring Framework 事件(如 ContextRefreshedEvent)之外,a 还会发送一些额外的应用程序事件。SpringApplication

某些事件实际上是在创建 之前触发的,因此您不能在这些事件上将侦听器注册为 . 可以使用方法或方法注册它们。ApplicationContext@BeanSpringApplication.addListeners(…​)SpringApplicationBuilder.listeners(…​)

如果希望自动注册这些侦听器,无论创建应用程序的方式如何,都可以将文件添加到项目中,并使用密钥引用侦听器,如以下示例所示:META-INF/spring.factoriesorg.springframework.context.ApplicationListener

org.springframework.context.ApplicationListener=com.example.project.MyListener

应用程序事件在应用程序运行时按以下顺序发送:

  1. An 在运行开始时但在任何处理之前发送,但侦听器和初始值设定项的注册除外。ApplicationStartingEvent

  2. 当上下文中要使用的 an 已知时,但在创建上下文之前发送 an。ApplicationEnvironmentPreparedEventEnvironment

  3. 在准备 ApplicationContextInitializers 并调用 ApplicationContextInitializers 时,但在加载任何 Bean 定义之前发送 An。ApplicationContextInitializedEventApplicationContext

  4. 在刷新开始之前,但在加载 Bean 定义之后发送 an。ApplicationPreparedEvent

  5. 在刷新上下文之后,但在调用任何应用程序和命令行运行器之前发送 an。ApplicationStartedEvent

  6. 紧随其后发送 an,以指示应用程序被视为活动。AvailabilityChangeEventLivenessState.CORRECT

  7. 在调用任何应用程序和命令行运行器后发送 an。ApplicationReadyEvent

  8. 紧随其后发送 an,以指示应用程序已准备好为请求提供服务。AvailabilityChangeEventReadinessState.ACCEPTING_TRAFFIC

  9. 如果启动时出现异常,则发送 An。ApplicationFailedEvent

上面的列表仅包括与 . 除此之外,以下事件还会在之后和之前发布:SpringApplicationEventSpringApplicationApplicationPreparedEventApplicationStartedEvent

  • A 在准备就绪后发送。 并且分别是 servlet 和反应变体。WebServerInitializedEventWebServerServletWebServerInitializedEventReactiveWebServerInitializedEvent

  • 刷新 an 时发送 a。ContextRefreshedEventApplicationContext

您通常不需要使用应用程序事件,但知道它们的存在会很方便。 在内部,Spring Boot 使用事件来处理各种任务。
默认情况下,事件侦听器不应运行可能很长的任务,因为它们在同一线程中执行。 请考虑改用应用程序和命令行运行器

应用程序事件是使用 Spring Framework 的事件发布机制发送的。 此机制的一部分可确保在子上下文中发布到侦听器的事件也会发布到任何祖先上下文中的侦听器。 因此,如果应用程序使用实例层次结构,则侦听器可能会收到同一类型应用程序事件的多个实例。SpringApplication

若要允许侦听器区分其上下文的事件和后代上下文的事件,它应请求注入其应用程序上下文,然后将注入的上下文与事件的上下文进行比较。 可以通过实现来注入上下文,或者,如果侦听器是 bean,则使用 .ApplicationContextAware@Autowired

某些事件实际上是在创建 之前触发的,因此您不能在这些事件上将侦听器注册为 . 可以使用方法或方法注册它们。ApplicationContext@BeanSpringApplication.addListeners(…​)SpringApplicationBuilder.listeners(…​)

如果希望自动注册这些侦听器,无论创建应用程序的方式如何,都可以将文件添加到项目中,并使用密钥引用侦听器,如以下示例所示:META-INF/spring.factoriesorg.springframework.context.ApplicationListener

org.springframework.context.ApplicationListener=com.example.project.MyListener
您通常不需要使用应用程序事件,但知道它们的存在会很方便。 在内部,Spring Boot 使用事件来处理各种任务。
默认情况下,事件侦听器不应运行可能很长的任务,因为它们在同一线程中执行。 请考虑改用应用程序和命令行运行器

Web 环境

A 尝试代表您创建正确的类型。 用于确定 a 的算法如下:SpringApplicationApplicationContextWebApplicationType

  • 如果存在 Spring MVC,则使用AnnotationConfigServletWebServerApplicationContext

  • 如果 Spring MVC 不存在,而 Spring WebFlux 存在,则使用AnnotationConfigReactiveWebServerApplicationContext

  • 否则,将使用AnnotationConfigApplicationContext

这意味着,如果您在同一应用程序中使用 Spring MVC 和 Spring WebFlux 中的新 MVC,则默认情况下将使用 Spring MVC。 您可以通过调用 轻松覆盖它。WebClientsetWebApplicationType(WebApplicationType)

也可以通过调用 来完全控制所使用的类型。ApplicationContextsetApplicationContextFactory(…​)

在 JUnit 测试中使用时,通常需要调用。setWebApplicationType(WebApplicationType.NONE)SpringApplication
在 JUnit 测试中使用时,通常需要调用。setWebApplicationType(WebApplicationType.NONE)SpringApplication

访问应用程序参数

如果需要访问传递给 的应用程序参数,可以注入 Bean。 该接口提供对原始参数以及分析和参数的访问,如以下示例所示:SpringApplication.run(…​)org.springframework.boot.ApplicationArgumentsApplicationArgumentsString[]optionnon-option

  • Java

  • Kotlin

import java.util.List;

import org.springframework.boot.ApplicationArguments;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

	public MyBean(ApplicationArguments args) {
		boolean debug = args.containsOption("debug");
		List<String> files = args.getNonOptionArgs();
		if (debug) {
			System.out.println(files);
		}
		// if run with "--debug logfile.txt" prints ["logfile.txt"]
	}

}
import org.springframework.boot.ApplicationArguments
import org.springframework.stereotype.Component

@Component
class MyBean(args: ApplicationArguments) {

	init {
		val debug = args.containsOption("debug")
		val files = args.nonOptionArgs
		if (debug) {
			println(files)
		}
		// if run with "--debug logfile.txt" prints ["logfile.txt"]
	}

}
Spring Boot 还向 Spring 注册了 a 。 这样,您还可以使用注释注入单个应用程序参数。CommandLinePropertySourceEnvironment@Value
Spring Boot 还向 Spring 注册了 a 。 这样,您还可以使用注释注入单个应用程序参数。CommandLinePropertySourceEnvironment@Value

使用 ApplicationRunner 或 CommandLineRunner

如果需要在启动后运行一些特定的代码,则可以实现 or 接口。 两个接口以相同的方式工作,并提供一个方法,该方法在完成之前调用。SpringApplicationApplicationRunnerCommandLineRunnerrunSpringApplication.run(…​)

此协定非常适合应在应用程序启动后但在开始接受流量之前运行的任务。

接口以字符串数组的形式提供对应用程序参数的访问,而接口使用前面讨论的接口。 以下示例显示了一个方法:CommandLineRunnerApplicationRunnerApplicationArgumentsCommandLineRunnerrun

  • Java

  • Kotlin

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class MyCommandLineRunner implements CommandLineRunner {

	@Override
	public void run(String... args) {
		// Do something...
	}

}
import org.springframework.boot.CommandLineRunner
import org.springframework.stereotype.Component

@Component
class MyCommandLineRunner : CommandLineRunner {

	override fun run(vararg args: String) {
		// Do something...
	}

}

如果定义了必须按特定顺序调用的多个或 Bean,则可以另外实现接口或使用注释。CommandLineRunnerApplicationRunnerorg.springframework.core.Orderedorg.springframework.core.annotation.Order

此协定非常适合应在应用程序启动后但在开始接受流量之前运行的任务。

应用程序退出

每个都向 JVM 注册一个关闭挂钩,以确保在退出时正常关闭。 可以使用所有标准的 Spring 生命周期回调(例如接口或注解)。SpringApplicationApplicationContextDisposableBean@PreDestroy

此外,如果 Bean 希望在调用时返回特定的退出代码,则可以实现该接口。 然后,可以传递此退出代码以将其作为状态代码返回,如以下示例所示:org.springframework.boot.ExitCodeGeneratorSpringApplication.exit()System.exit()

  • Java

  • Kotlin

import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class MyApplication {

	@Bean
	public ExitCodeGenerator exitCodeGenerator() {
		return () -> 42;
	}

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

}
import org.springframework.boot.ExitCodeGenerator
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean

import kotlin.system.exitProcess

@SpringBootApplication
class MyApplication {

	@Bean
	fun exitCodeGenerator() = ExitCodeGenerator { 42 }

}

fun main(args: Array<String>) {
	exitProcess(SpringApplication.exit(
		runApplication<MyApplication>(*args)))
}

此外,接口可以通过异常实现。 当遇到此类异常时,Spring Boot 将返回实现方法提供的退出代码。ExitCodeGeneratorgetExitCode()

如果有多个,则使用生成的第一个非零退出代码。 要控制生成器的调用顺序,请另外实现接口或使用注释。ExitCodeGeneratororg.springframework.core.Orderedorg.springframework.core.annotation.Order

管理员功能

可以通过指定属性为应用程序启用与管理员相关的功能。 这将在平台上公开 SpringApplicationAdminMXBean 。 您可以使用此功能远程管理 Spring Boot 应用程序。 此功能对于任何服务包装器实现也很有用。spring.application.admin.enabledMBeanServer

如果想知道应用程序在哪个 HTTP 端口上运行,请获取键为 的属性。local.server.port
如果想知道应用程序在哪个 HTTP 端口上运行,请获取键为 的属性。local.server.port

应用程序启动跟踪

在应用程序启动期间,执行与应用程序生命周期相关的许多任务, Bean 生命周期,甚至处理应用程序事件。 使用 ApplicationStartup,Spring Framework 允许您使用 StartupStep 对象跟踪应用程序启动顺序。 收集这些数据可以用于分析目的,或者只是为了更好地了解应用程序启动过程。SpringApplicationApplicationContext

您可以在设置实例时选择一个实施。 例如,要使用 ,可以写:ApplicationStartupSpringApplicationBufferingApplicationStartup

  • Java

  • Kotlin

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;

@SpringBootApplication
public class MyApplication {

	public static void main(String[] args) {
		SpringApplication application = new SpringApplication(MyApplication.class);
		application.setApplicationStartup(new BufferingApplicationStartup(2048));
		application.run(args);
	}

}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup
import org.springframework.boot.runApplication

@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
	runApplication<MyApplication>(*args) {
		applicationStartup = BufferingApplicationStartup(2048)
	}
}

第一个可用的实现是由 Spring Framework 提供的。 它将特定于 Spring 的启动事件添加到 Java Flight Recorder 会话中,用于分析应用程序并将其 Spring 上下文生命周期与 JVM 事件(例如分配、GC、类加载等)相关联。 配置后,您可以通过在启用飞行记录器的情况下运行应用程序来记录数据:FlightRecorderApplicationStartup

$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar

Spring Boot 随变体一起提供;此实现用于缓冲启动步骤并将其排入外部指标系统。 应用程序可以在任何组件中请求 bean 类型。BufferingApplicationStartupBufferingApplicationStartup

Spring Boot 还可以配置为公开以 JSON 文档形式提供此信息的启动端点

虚拟线程

如果在 Java 21 或更高版本上运行,则可以通过将属性设置为 来启用虚拟线程。spring.threads.virtual.enabledtrue

在为应用程序启用此选项之前,应考虑阅读官方的 Java 虚拟线程文档。 在某些情况下,由于“固定虚拟线程”,应用程序可能会遇到较低的吞吐量;本页还介绍了如何使用 JDK Flight Recorder 或 CLI 检测此类情况。jcmd

虚拟线程的一个副作用是它们是守护进程线程。 如果 JVM 的所有线程都是守护进程线程,则 JVM 将退出。 例如,当您依赖 Bean 来保持应用程序处于活动状态时,此行为可能会成为问题。 如果使用虚拟线程,则调度程序线程是虚拟线程,因此是守护进程线程,不会使 JVM 保持活动状态。 这不仅会影响调度,其他技术也会受到影响。 要使 JVM 在所有情况下都保持运行,建议将该属性设置为 。 这可确保 JVM 保持活动状态,即使所有线程都是虚拟线程也是如此。@Scheduledspring.main.keep-alivetrue
虚拟线程的一个副作用是它们是守护进程线程。 如果 JVM 的所有线程都是守护进程线程,则 JVM 将退出。 例如,当您依赖 Bean 来保持应用程序处于活动状态时,此行为可能会成为问题。 如果使用虚拟线程,则调度程序线程是虚拟线程,因此是守护进程线程,不会使 JVM 保持活动状态。 这不仅会影响调度,其他技术也会受到影响。 要使 JVM 在所有情况下都保持运行,建议将该属性设置为 。 这可确保 JVM 保持活动状态,即使所有线程都是虚拟线程也是如此。@Scheduledspring.main.keep-alivetrue