SpringApplication

SpringApplication 類別提供了一個方便的方式來引導從 main() 方法啟動的 Spring 應用程式。在許多情況下,您可以委派給靜態的 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)
}

當您的應用程式啟動時,您應該會看到類似以下的輸出

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

 :: Spring Boot ::                (v3.3.5)

2024-10-24T12:03:05.386Z  INFO 112801 --- [           main] o.s.b.d.f.logexample.MyApplication       : Starting MyApplication using Java 17.0.13 with PID 112801 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
2024-10-24T12:03:05.406Z  INFO 112801 --- [           main] o.s.b.d.f.logexample.MyApplication       : No active profile set, falling back to 1 default profile: "default"
2024-10-24T12:03:08.644Z  INFO 112801 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2024-10-24T12:03:08.685Z  INFO 112801 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-10-24T12:03:08.690Z  INFO 112801 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.31]
2024-10-24T12:03:08.898Z  INFO 112801 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-10-24T12:03:08.900Z  INFO 112801 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3244 ms
2024-10-24T12:03:10.275Z  INFO 112801 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2024-10-24T12:03:10.290Z  INFO 112801 --- [           main] o.s.b.d.f.logexample.MyApplication       : Started MyApplication in 5.964 seconds (process running for 7.025)

預設情況下,會顯示 INFO 日誌訊息,包括一些相關的啟動詳細資訊,例如啟動應用程式的使用者。如果您需要 INFO 以外的日誌級別,您可以設定它,如 日誌級別 中所述。應用程式版本是使用主要應用程式類別套件中的實作版本來決定的。啟動資訊日誌記錄可以透過將 spring.main.log-startup-info 設定為 false 來關閉。這也會關閉應用程式活動設定檔的日誌記錄。

若要在啟動期間新增額外的日誌記錄,您可以覆寫 SpringApplication 子類別中的 logStartupInfo(boolean)

啟動失敗

如果您的應用程式啟動失敗,已註冊的 FailureAnalyzers 有機會提供專用的錯誤訊息和具體的動作來修正問題。例如,如果您在連接埠 8080 上啟動網路應用程式,而該連接埠已被使用,您應該會看到類似以下的訊息

***************************
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 屬性 或為 `org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener` 啟用 DEBUG 日誌記錄

例如,如果您使用 java -jar 執行應用程式,您可以如下所示啟用 debug 屬性

$ java -jar myproject-0.0.1-SNAPSHOT.jar --debug

延遲初始化

SpringApplication 允許延遲初始化應用程式。當啟用延遲初始化時,bean 會在需要時建立,而不是在應用程式啟動期間建立。因此,啟用延遲初始化可以縮短應用程式啟動所需的時間。在網路應用程式中,啟用延遲初始化將導致許多與網路相關的 bean 在收到 HTTP 請求之前不會初始化。

延遲初始化的缺點是它可能會延遲發現應用程式的問題。如果設定錯誤的 bean 是延遲初始化的,則失敗將不再在啟動期間發生,問題只會在 bean 初始化時才會顯現。還必須注意確保 JVM 有足夠的記憶體來容納應用程式的所有 bean,而不僅僅是在啟動期間初始化的那些 bean。基於這些原因,延遲初始化預設未啟用,建議在啟用延遲初始化之前,先對 JVM 的堆積大小進行微調。

可以使用 `SpringApplicationBuilder` 上的 `lazyInitialization` 方法或 `SpringApplication` 上的 `setLazyInitialization` 方法以程式設計方式啟用延遲初始化。或者,可以使用 `spring.main.lazy-initialization` 屬性啟用,如下列範例所示

  • 屬性

  • YAML

spring.main.lazy-initialization=true
spring:
  main:
    lazy-initialization: true
如果您想在應用程式的其餘部分使用延遲初始化時,針對某些 bean 停用延遲初始化,您可以使用 `@Lazy(false)` 註解明確地將其 lazy 屬性設定為 false。

自訂 Banner

啟動時列印的 banner 可以透過將 `banner.txt` 檔案新增至您的類別路徑,或將 `spring.banner.location` 屬性設定為此類檔案的位置來變更。如果檔案的編碼不是 UTF-8,您可以設定 `spring.banner.charset`。

在您的 `banner.txt` 檔案中,您可以使用 `Environment` 中可用的任何鍵,以及下列任何預留位置

表 1. Banner 變數
變數 描述

${application.version}

您的應用程式的版本號碼,如 `MANIFEST.MF` 中宣告。例如,`Implementation-Version: 1.0` 會列印為 `1.0`。

${application.formatted-version}

您的應用程式的版本號碼,如 `MANIFEST.MF` 中宣告,並格式化以供顯示(用括號括住並以 `v` 作為前綴)。例如 `(v1.0)`。

${spring-boot.version}

您正在使用的 Spring Boot 版本。例如 `3.3.5`。

${spring-boot.formatted-version}

您正在使用的 Spring Boot 版本,格式化以供顯示(用括號括住並以 `v` 作為前綴)。例如 `(v3.3.5)`。

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

其中 `NAME` 是 ANSI 逸出碼的名稱。請參閱 `AnsiPropertySource` 以取得詳細資訊。

${application.title}

您的應用程式的標題,如 `MANIFEST.MF` 中宣告。例如 `Implementation-Title: MyApp` 會列印為 `MyApp`。

如果您想以程式設計方式產生 banner,可以使用 `SpringApplication.setBanner(…​)` 方法。使用 `org.springframework.boot.Banner` 介面並實作您自己的 `printBanner()` 方法。

您也可以使用 `spring.main.banner-mode` 屬性來決定是否必須在 `System.out` (`console`) 上列印 banner、傳送至已設定的日誌記錄器 (`log`),或完全不產生 (`off`)。

列印的 banner 會以單例 bean 的形式註冊,名稱如下:`springBootBanner`。

application.titleapplication.versionapplication.formatted-version 屬性僅在您使用 `java -jar` 或 `java -cp` 與 Spring Boot 啟動器時才可用。如果您執行未封裝的 jar 並使用 `java -cp <classpath> <mainclass>` 啟動它,或將您的應用程式作為 native image 執行,則這些值將不會被解析。

若要使用 application. 屬性,請使用 `java -jar` 以封裝的 jar 形式啟動您的應用程式,或使用 `java org.springframework.boot.loader.launch.JarLauncher` 以未封裝的 jar 形式啟動。這會在建置類別路徑和啟動您的應用程式之前初始化 application. banner 屬性。

自訂 SpringApplication

如果 `SpringApplication` 預設值不符合您的喜好,您可以改為建立本機實例並自訂它。例如,若要關閉 banner,您可以撰寫

  • 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)
	}
}
傳遞給 `SpringApplication` 的建構子引數是 Spring bean 的組態來源。在大多數情況下,這些是對 `@Configuration` 類別的參考,但它們也可能是對 `@Component` 類別的直接參考。

也可以使用 `application.properties` 檔案來設定 `SpringApplication`。有關詳細資訊,請參閱 外部化組態

如需組態選項的完整清單,請參閱 `SpringApplication` API 文件。

Fluent Builder API

如果您需要建置 `ApplicationContext` 階層(具有父/子關係的多個 Context),或者如果您偏好使用 fluent builder API,則可以使用 `SpringApplicationBuilder`。

`SpringApplicationBuilder` 可讓您將多個方法呼叫鏈結在一起,並包含 `parent` 和 `child` 方法,讓您建立階層,如下列範例所示

  • 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)
在建立 `ApplicationContext` 階層時,有一些限制。例如,Web 元件 必須 包含在子 Context 中,並且父 Context 和子 Context 都使用相同的 `Environment`。如需完整詳細資訊,請參閱 `SpringApplicationBuilder` API 文件。

應用程式可用性

當部署在平台上時,應用程式可以使用 Kubernetes Probes 等基礎架構,向平台提供有關其可用性的資訊。Spring Boot 包含對常用 “liveness” 和 “readiness” 可用性狀態的開箱即用支援。如果您正在使用 Spring Boot 的 “actuator” 支援,則這些狀態會公開為健康檢查端點群組。

此外,您也可以透過將 `ApplicationAvailability` 介面注入到您自己的 bean 中來取得可用性狀態。

Liveness 狀態

應用程式的 “Liveness” 狀態會告知其內部狀態是否允許它正常運作,或在目前發生故障時自行恢復。損壞的 “Liveness” 狀態表示應用程式處於無法恢復的狀態,基礎架構應重新啟動應用程式。

一般而言,“Liveness” 狀態不應基於外部檢查,例如 健康檢查。如果這樣做,失敗的外部系統(資料庫、Web API、外部快取)將會觸發平台上的大規模重新啟動和連鎖故障。

Spring Boot 應用程式的內部狀態主要由 Spring `ApplicationContext` 表示。如果應用程式 Context 已成功啟動,Spring Boot 會假設應用程式處於有效狀態。應用程式在 Context 重新整理後立即被視為 live,請參閱 Spring Boot 應用程式生命週期和相關的應用程式事件

Readiness 狀態

應用程式的 “Readiness” 狀態會告知應用程式是否已準備好處理流量。失敗的 “Readiness” 狀態會告知平台,目前不應將流量路由到應用程式。這通常發生在啟動期間,當 `CommandLineRunner` 和 `ApplicationRunner` 元件正在處理時,或在應用程式認為它太忙而無法處理額外流量的任何時間。

應用程式在應用程式和命令列執行器被呼叫後立即被視為 ready,請參閱 Spring Boot 應用程式生命週期和相關的應用程式事件

預期在啟動期間執行的任務應由 `CommandLineRunner` 和 `ApplicationRunner` 元件執行,而不是使用 Spring 元件生命週期回呼,例如 `@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)
		}
	}

}

應用程式事件和監聽器

除了常見的 Spring Framework 事件,例如 `ContextRefreshedEvent`,`SpringApplication` 還會傳送一些額外的應用程式事件。

有些事件實際上是在建立 `ApplicationContext` 之前觸發的,因此您無法將這些事件上的監聽器註冊為 `@Bean`。您可以使用 `SpringApplication.addListeners(…​)` 方法或 `SpringApplicationBuilder.listeners(…​)` 方法來註冊它們。

如果您希望自動註冊這些監聽器,無論應用程式的建立方式為何,您可以將 `META-INF/spring.factories` 檔案新增至您的專案,並使用 `org.springframework.context.ApplicationListener` 鍵來參考您的監聽器,如下列範例所示

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

應用程式事件在您的應用程式執行時,會依下列順序傳送

  1. ApplicationStartingEvent 在執行開始時傳送,但在任何處理之前,除了監聽器和初始化器的註冊。

  2. 當要用於 Context 中的 Environment 已知時,但在建立 Context 之前,會傳送 ApplicationEnvironmentPreparedEvent

  3. 當 `ApplicationContext` 已準備好且 ApplicationContextInitializers 已被呼叫,但在載入任何 bean 定義之前,會傳送 ApplicationContextInitializedEvent

  4. ApplicationPreparedEvent 在重新整理開始之前立即傳送,但在 bean 定義已載入之後。

  5. ApplicationStartedEvent 在 Context 重新整理之後傳送,但在任何應用程式和命令列執行器被呼叫之前。

  6. AvailabilityChangeEvent 緊接著傳送,並帶有 LivenessState.CORRECT,以指示應用程式被視為 live。

  7. ApplicationReadyEvent 在任何 應用程式和命令列執行器 被呼叫之後傳送。

  8. AvailabilityChangeEvent 緊接著傳送,並帶有 ReadinessState.ACCEPTING_TRAFFIC,以指示應用程式已準備好為請求提供服務。

  9. 如果在啟動時發生例外狀況,則會傳送 ApplicationFailedEvent

上述清單僅包含與 `SpringApplication` 相關聯的 `SpringApplicationEvent`。除了這些之外,在 `ApplicationPreparedEvent` 之後和 `ApplicationStartedEvent` 之前也會發布下列事件

  • WebServerInitializedEventWebServer 準備就緒後傳送。ServletWebServerInitializedEventReactiveWebServerInitializedEvent 分別是 servlet 和 reactive 變體。

  • 當 `ApplicationContext` 重新整理時,會傳送 ContextRefreshedEvent

您通常不需要使用應用程式事件,但知道它們存在可能會很有用。在內部,Spring Boot 使用事件來處理各種任務。
事件監聽器不應執行可能耗時的任務,因為它們預設在同一個執行緒中執行。請考慮改用 應用程式和命令列執行器

應用程式事件是使用 Spring Framework 的事件發布機制傳送的。此機制的一部分確保發布到子 Context 中監聽器的事件也會發布到任何祖先 Context 中的監聽器。因此,如果您的應用程式使用 `SpringApplication` 實例的階層,則監聽器可能會收到相同類型應用程式事件的多個實例。

為了讓您的監聽器區分其 Context 的事件和後代 Context 的事件,它應該要求注入其應用程式 Context,然後將注入的 Context 與事件的 Context 進行比較。可以透過實作 `ApplicationContextAware` 或,如果監聽器是 bean,則透過使用 `@Autowired` 來注入 Context。

網路環境

SpringApplication 會嘗試代表您建立正確類型的 `ApplicationContext`。用於判斷 `WebApplicationType` 的演算法如下

  • 如果 Spring MVC 存在,則會使用 `AnnotationConfigServletWebServerApplicationContext`

  • 如果 Spring MVC 不存在且 Spring WebFlux 存在,則會使用 `AnnotationConfigReactiveWebServerApplicationContext`

  • 否則,會使用 `AnnotationConfigApplicationContext`

這表示如果您在同一個應用程式中使用 Spring MVC 和 Spring WebFlux 中的新 `WebClient`,則預設會使用 Spring MVC。您可以透過呼叫 `setWebApplicationType(WebApplicationType)` 輕鬆覆寫它。

也可以透過呼叫 `setApplicationContextFactory(…​)` 完全控制所使用的 `ApplicationContext` 類型。

在 JUnit 測試中使用 `SpringApplication` 時,通常需要呼叫 `setWebApplicationType(WebApplicationType.NONE)`。

存取應用程式引數

如果您需要存取傳遞給 `SpringApplication.run(…​)` 的應用程式引數,您可以注入 `org.springframework.boot.ApplicationArguments` bean。`ApplicationArguments` 介面提供對原始 `String[]` 引數以及已解析的 `option` 和 `non-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 `Environment` 註冊 `CommandLinePropertySource`。這也讓您可以使用 `@Value` 註解注入單個應用程式引數。

使用 ApplicationRunner 或 CommandLineRunner

如果您需要在 `SpringApplication` 啟動後執行一些特定的程式碼,您可以實作 `ApplicationRunner` 或 `CommandLineRunner` 介面。這兩個介面以相同的方式運作,並提供單一的 `run` 方法,該方法在 `SpringApplication.run(…​)` 完成之前立即呼叫。

此合約非常適合在應用程式啟動後但在開始接受流量之前應執行的任務。

`CommandLineRunner` 介面提供對應用程式引數的字串陣列存取,而 `ApplicationRunner` 使用前面討論的 `ApplicationArguments` 介面。下列範例顯示具有 `run` 方法的 `CommandLineRunner`

  • 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...
	}

}

如果定義了多個 `CommandLineRunner` 或 `ApplicationRunner` bean,且必須依特定順序呼叫,您可以額外實作 `org.springframework.core.Ordered` 介面或使用 `org.springframework.core.annotation.Order` 註解。

應用程式結束

每個 `SpringApplication` 都會在 JVM 中註冊一個關閉 hook,以確保 `ApplicationContext` 在結束時優雅地關閉。可以使用所有標準的 Spring 生命週期回呼(例如 `DisposableBean` 介面或 `@PreDestroy` 註解)。

此外,如果 bean 希望在呼叫 `SpringApplication.exit()` 時傳回特定的結束代碼,則可以實作 `org.springframework.boot.ExitCodeGenerator` 介面。然後可以將此結束代碼傳遞給 `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)))
}

此外,`ExitCodeGenerator` 介面可以由例外狀況實作。當遇到此類例外狀況時,Spring Boot 會傳回實作的 `getExitCode()` 方法所提供的結束代碼。

如果有多個 `ExitCodeGenerator`,則會使用產生的第一個非零結束代碼。若要控制呼叫產生器的順序,請額外實作 `org.springframework.core.Ordered` 介面或使用 `org.springframework.core.annotation.Order` 註解。

管理功能

可以透過指定 `spring.application.admin.enabled` 屬性來啟用應用程式的管理相關功能。這會在平台 `MBeanServer` 上公開 `SpringApplicationAdminMXBean`。您可以使用此功能遠端管理您的 Spring Boot 應用程式。此功能對於任何服務包裝器實作也可能很有用。

如果您想知道應用程式正在哪個 HTTP 連接埠上執行,請取得金鑰為 `local.server.port` 的屬性。

應用程式啟動追蹤

在應用程式啟動期間,`SpringApplication` 和 `ApplicationContext` 會執行許多與應用程式生命週期、bean 生命週期甚至處理應用程式事件相關的任務。透過 `ApplicationStartup`,Spring Framework 可讓您使用 `StartupStep` 物件追蹤應用程式啟動順序。可以收集此資料以用於分析目的,或僅僅是為了更好地了解應用程式啟動過程。

您可以在設定 `SpringApplication` 實例時選擇 `ApplicationStartup` 實作。例如,若要使用 `BufferingApplicationStartup`,您可以撰寫

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

第一個可用的實作 FlightRecorderApplicationStartup 由 Spring Framework 提供。它將 Spring 特有的啟動事件新增至 Java Flight Recorder 工作階段,旨在分析應用程式效能,並將其 Spring 內容生命週期與 JVM 事件(例如記憶體配置、GC、類別載入…等)相關聯。一旦完成設定,您就可以透過在啟用 Flight Recorder 的情況下執行應用程式來記錄資料

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

Spring Boot 隨附 BufferingApplicationStartup 變體;此實作旨在緩衝啟動步驟,並將其排入外部指標系統。應用程式可以在任何元件中要求 BufferingApplicationStartup 類型的 Bean。

Spring Boot 也可以設定為公開 startup 端點,以 JSON 文件形式提供此資訊。

虛擬執行緒

如果您在 Java 21 或更高版本上執行,您可以將 spring.threads.virtual.enabled 屬性設定為 true 來啟用虛擬執行緒。

在為您的應用程式開啟此選項之前,您應該考慮閱讀官方 Java 虛擬執行緒文件。在某些情況下,應用程式可能會因為「Pinned Virtual Threads」(釘選的虛擬執行緒)而導致較低的吞吐量;此頁面也說明如何使用 JDK Flight Recorder 或 jcmd CLI 偵測此類情況。

如果啟用虛擬執行緒,則設定執行緒池的屬性將不再生效。這是因為虛擬執行緒排程在 JVM 全域平台執行緒池上,而不是在專用執行緒池上。
虛擬執行緒的一個副作用是它們是守護執行緒。如果 JVM 的所有執行緒都是守護執行緒,則 JVM 將會退出。當您依賴 @Scheduled Bean(例如,為了保持應用程式運作)時,此行為可能會成為問題。如果您使用虛擬執行緒,排程器執行緒是虛擬執行緒,因此也是守護執行緒,並且不會保持 JVM 運作。這不僅影響排程,也可能發生在其他技術上。為了在所有情況下保持 JVM 運作,建議將 spring.main.keep-alive 屬性設定為 true。這可確保 JVM 保持運作,即使所有執行緒都是虛擬執行緒。