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.1)

2024-06-20T10:08:25.916Z  INFO 112065 --- [           main] o.s.b.d.f.logexample.MyApplication       : Starting MyApplication using Java 17.0.11 with PID 112065 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
2024-06-20T10:08:25.931Z  INFO 112065 --- [           main] o.s.b.d.f.logexample.MyApplication       : No active profile set, falling back to 1 default profile: "default"
2024-06-20T10:08:28.799Z  INFO 112065 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2024-06-20T10:08:28.828Z  INFO 112065 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-06-20T10:08:28.841Z  INFO 112065 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.25]
2024-06-20T10:08:29.018Z  INFO 112065 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-06-20T10:08:29.030Z  INFO 112065 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2892 ms
2024-06-20T10:08:30.841Z  INFO 112065 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path '/'
2024-06-20T10:08:30.878Z  INFO 112065 --- [           main] o.s.b.d.f.logexample.MyApplication       : Started MyApplication in 6.515 seconds (process running for 8.658)

デフォルトでは、INFO ロギングメッセージが表示されます。これには、アプリケーションを起動したユーザーなど、関連するスタートアップの詳細が含まれます。INFO 以外のログレベルが必要な場合は、ログレベルの説明に従って設定できます。アプリケーションバージョンは、メインアプリケーションクラスのパッケージの実装バージョンを使用して決定されます。spring.main.log-startup-info を false に設定することにより、始動情報のロギングをオフにできます。これにより、アプリケーションのアクティブなプロファイルのログもオフになります。

起動時に追加のログを追加するには、SpringApplication のサブクラスで logStartupInfo(boolean) をオーバーライドできます。

起動失敗

アプリケーションの起動に失敗した場合、登録された FailureAnalyzers は、専用のエラーメッセージと、問題を修正するための具体的なアクションを提供する機会を得ます。たとえば、ポート 8080 で Web アプリケーションを起動し、そのポートがすでに使用されている場合、次のようなメッセージが表示されます。

***************************
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 実装を提供しており、独自の FailureAnalyzer 実装を追加できます。

例外を処理できる障害アナライザーがない場合でも、完全な状態レポートを表示して、何が問題になったのかをよりよく理解できます。これを行うには、debug プロパティを有効にするか、org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListenerDEBUG ロギングを有効にする必要があります。

たとえば、java -jar を使用してアプリケーションを実行している場合、次のように debug プロパティを有効にできます。

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

遅延初期化

SpringApplication を使用すると、アプリケーションを遅延的に初期化できます。遅延初期化が有効な場合、Bean はアプリケーションの起動時ではなく、必要に応じて作成されます。その結果、遅延初期化を有効にすると、アプリケーションの起動にかかる時間を短縮できます。Web アプリケーションでは、遅延初期化を有効にすると、HTTP リクエストを受信するまで多くの Web 関連 Bean が初期化されなくなります。

遅延初期化の欠点は、アプリケーションの問題の発見を遅らせる可能性があることです。誤って構成された 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) アノテーションを使用して遅延属性を明示的に false に設定できます。

バナーのカスタマイズ

起動時に出力されるバナーは、クラスパスに banner.txt ファイルを追加するか、spring.banner.location プロパティをそのようなファイルの場所に設定することで変更できます。ファイルに UTF-8 以外のエンコーディングがある場合は、spring.banner.charset を設定できます。

banner.txt ファイル内では、Environment で使用可能な任意のキーと、次のプレースホルダーのいずれかを使用できます。

表 1: バナー変数
変数 説明

${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.1.

${spring-boot.formatted-version}

使用する Spring Boot バージョン。表示用にフォーマットされています(括弧で囲まれ、接頭部が v)。たとえば、(v3.3.1)

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

Where NAME is the name of an ANSI escape code. See AnsiPropertySource (Javadoc) for details.

${application.title}

MANIFEST.MF で宣言されているアプリケーションのタイトル。たとえば、Implementation-Title: MyApp は MyApp として出力されます。

SpringApplication.setBanner(…​) メソッドは、プログラムでバナーを生成する場合に使用できます。org.springframework.boot.Banner インターフェースを使用して、独自の printBanner() メソッドを実装します。

spring.main.banner-mode プロパティを使用して、バナーを System.out (console)に出力するか、構成されたロガーに送信する(log)か、まったく生成しない(off)かを決定することもできます。

出力されたバナーは、springBootBanner という名前でシングルトン Bean として登録されます。

application.titleapplication.versionapplication.formatted-version プロパティは、Spring Boot ランチャーで java -jar または java -cp を使用している場合にのみ使用できます。解凍された jar を実行していて java -cp <classpath> <mainclass> で起動している場合、またはアプリケーションをネイティブイメージとして実行している場合、値は解決されません。

application. プロパティを使用するには、アプリケーションを 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)
	}
}
SpringApplication に渡されるコンストラクター引数は、Spring Bean の構成ソースです。ほとんどの場合、これらは @Configuration クラスへの参照ですが、@Component クラスへの直接参照である場合もあります。

application.properties ファイルを使用して SpringApplication を構成することもできます。詳細については、環境別の設定切り替えを参照してください。

構成オプションの完全なリストについては、SpringApplication Javadoc を参照してください。

Fluent Builder API

ApplicationContext 階層(親 / 子関連を持つ複数のコンテキスト)を構築する必要がある場合、または「流れるような」ビルダー 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 コンポーネントは子コンテキスト内に含まれている必要があり、同じ Environment が親コンテキストと子コンテキストの両方に使用されます。詳細については、SpringApplicationBuilder Javadoc を参照してください。

アプリケーションの可用性

アプリケーションをプラットフォームにデプロイすると、Kubernetes プローブ (英語) などのインフラストラクチャを使用して、アプリケーションがその可用性に関する情報をプラットフォームに提供できます。Spring Boot には、一般的に使用される「活性」と「準備」の可用性状態のサポートが含まれています。Spring Boot の「アクチュエーター」サポートを使用している場合、これらの状態はヘルスエンドポイントグループとして公開されます。

さらに、ApplicationAvailability インターフェースを独自の Bean に挿入することにより、可用性の状態を取得することもできます。

活性状態

アプリケーションの「活性」状態は、その内部状態によってアプリケーションが正しく機能するかどうか、現在障害が発生している場合は自動的に回復するかどうかを示します。壊れた「活性」状態は、アプリケーションが回復できない状態にあり、インフラストラクチャがアプリケーションを再起動する必要があることを意味します。

一般に、「活性」状態はヘルス診断などの外部チェックに基づくべきではありません。その場合、障害のある外部システム(データベース、Web API、外部キャッシュ)により、プラットフォーム全体で大規模な再起動とカスケード障害がトリガーされます。

Spring Boot アプリケーションの内部状態は、主に Spring ApplicationContext で表されます。アプリケーションコンテキストが正常に開始された場合、Spring Boot はアプリケーションが有効な状態にあると想定します。アプリケーションは、コンテキストがリフレッシュされるとすぐにライブと見なされます。Spring Boot アプリケーションのライフサイクルと関連するアプリケーションイベントを参照してください。

準備状態

アプリケーションの「準備完了」状態は、アプリケーションがトラフィックを処理する準備ができているかどうかを示します。失敗した「準備完了」状態は、今のところトラフィックをアプリケーションにルーティングするべきではないことをプラットフォームに通知します。これは通常、起動中、CommandLineRunner および ApplicationRunner コンポーネントの処理中、またはアプリケーションが追加のトラフィックに対してビジーすぎると判断した場合に発生します。

アプリケーションとコマンドラインランナーが呼び出されるとすぐに、アプリケーションは準備ができていると見なされます。Spring Boot アプリケーションのライフサイクルと関連するアプリケーションイベントを参照してください。

起動時に実行されることが予想されるタスクは、@PostConstruct などの Spring コンポーネントライフサイクルコールバックを使用する代わりに、CommandLineRunner および ApplicationRunner コンポーネントによって実行される必要があります。

アプリケーションの可用性状態の管理

アプリケーションコンポーネントは、ApplicationAvailability インターフェースを挿入し、その上でメソッドを呼び出すことにより、いつでも現在の可用性の状態を取得できます。多くの場合、アプリケーションは状態の更新をリッスンしたり、アプリケーションの状態を更新したりします。

例: アプリケーションの「準備」状態をファイルにエクスポートして、Kubernetes の「exec プローブ」がこのファイルを確認できるようにします。

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

}

アプリケーションイベントとリスナー

ContextRefreshedEvent (Javadoc) などの通常の Spring Framework イベントに加えて、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. ApplicationEnvironmentPreparedEvent は、コンテキストで使用される Environment がわかっているが、コンテキストが作成される前に送信されます。

  3. ApplicationContextInitializedEvent は、ApplicationContext が準備され、ApplicationContextInitializers が呼び出されましたが、Bean 定義がロードされる前に送信されます。

  4. ApplicationPreparedEvent は、リフレッシュが開始される直前、ただし Bean 定義がロードされた後に送信されます。

  5. ApplicationStartedEvent は、コンテキストがリフレッシュされた後、アプリケーションとコマンドラインランナーが呼び出される前に送信されます。

  6. LivenessState.CORRECT の直後に AvailabilityChangeEvent が送信され、アプリケーションがライブと見なされることが示されます。

  7. ApplicationReadyEvent は、アプリケーションとコマンドラインランナーが呼び出された後に送信されます。

  8. AvailabilityChangeEvent は ReadinessState.ACCEPTING_TRAFFIC の直後に送信され、アプリケーションがリクエストを処理する準備ができていることを示します。

  9. 起動時に例外がある場合、ApplicationFailedEvent が送信されます。

上記のリストには、SpringApplication に関連付けられている SpringApplicationEvent のみが含まれています。これらに加えて、次のイベントも ApplicationPreparedEvent の後、ApplicationStartedEvent の前に公開されます。

  • WebServer の準備が整うと、WebServerInitializedEvent が送信されます。ServletWebServerInitializedEvent と ReactiveWebServerInitializedEvent は、それぞれサーブレットとリアクティブバリアントです。

  • ApplicationContext がリフレッシュされると、ContextRefreshedEvent が送信されます。

多くの場合、アプリケーションイベントを使用する必要はありませんが、それらが存在することを知っておくと便利です。内部的に、Spring Boot はイベントを使用してさまざまなタスクを処理します。
イベントリスナーは、デフォルトでは同じスレッドで実行されるため、長時間かかる可能性のあるタスクを実行しないでください。代わりに、アプリケーションランナーとコマンドラインランナーの使用を検討してください。

アプリケーションイベントは、Spring Framework のイベント発行メカニズムを使用して送信されます。このメカニズムの一部により、子コンテキストでリスナーに発行されたイベントは、すべての祖先コンテキストでリスナーにも発行されます。この結果、アプリケーションが SpringApplication インスタンスの階層を使用している場合、リスナーは同じタイプのアプリケーションイベントの複数のインスタンスを受け取る場合があります。

リスナーがそのコンテキストのイベントと子孫コンテキストのイベントを区別できるようにするには、アプリケーションコンテキストの注入をリクエストし、注入されたコンテキストをイベントのコンテキストと比較する必要があります。コンテキストは、ApplicationContextAware を実装するか、リスナーが Bean の場合は @Autowired を使用して注入できます。

Web 環境

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 は、CommandLinePropertySource を Spring Environment に登録します。これにより、@Value アノテーションを使用して、単一のアプリケーション引数を注入することもできます。

ApplicationRunner または CommandLineRunner の使用

SpringApplication の起動後に特定のコードを実行する必要がある場合は、ApplicationRunner または CommandLineRunner インターフェースを実装できます。両方のインターフェースは同じように機能し、SpringApplication.run(…​) が完了する直前に呼び出される単一の 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 に登録して、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 プロパティを指定することにより、アプリケーションの管理関連機能を有効にすることができます。これにより、プラットフォーム MBeanServerSpringApplicationAdminMXBean (Javadoc) が公開されます。この機能を使用して、Spring Boot アプリケーションをリモートで管理できます。この機能は、サービスラッパーの実装にも役立ちます。

アプリケーションが実行されている HTTP ポートを知りたい場合は、local.server.port のキーを持つプロパティを取得します。

アプリケーションのスタートアップの追跡

アプリケーションの起動時に、SpringApplication と ApplicationContext は、アプリケーションのライフサイクル、Bean のライフサイクル、さらにはアプリケーションイベントの処理に関連する多くのタスクを実行します。ApplicationStartup (Javadoc) を使用すると、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、クラスの読み込みなど)と相関させることを目的としています。構成が完了すると、フライトレコーダーを有効にしてアプリケーションを実行することでデータを記録できます。

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

Spring Boot には BufferingApplicationStartup バリアントが付属しています。この実装は、起動ステップをバッファリングし、外部メトリクスシステムに排出することを目的としています。アプリケーションは、任意のコンポーネントで型 BufferingApplicationStartup の Bean を要求できます。

Spring Boot は、この情報を JSON ドキュメントとして提供する startup エンドポイントを公開するように構成することもできます。

仮想スレッド

Java 21 以降で実行している場合は、プロパティ spring.threads.virtual.enabled を true に設定することで仮想スレッドを有効にできます。

アプリケーションでこのオプションをオンにする前に、Java 仮想スレッドの公式ドキュメントを読む [Oracle] ことを検討してください。場合によっては、「固定された仮想スレッド」が原因でアプリケーションのスループットが低下することがあります。このページでは、JDK Flight Recorder または jcmd CLI を使用してそのようなケースを検出する方法についても説明します。

仮想スレッドの副作用の 1 つは、仮想スレッドがデーモンスレッドであることです。JVM のすべてのスレッドがデーモンスレッドである場合、JVM は終了します。この動作は、たとえばアプリケーションを存続させるために @Scheduled Bean に依存している場合に問題になる可能性があります。仮想スレッドを使用する場合、スケジューラスレッドは仮想スレッドであるため、デーモンスレッドとなり、JVM を存続させ続けることはありません。これはスケジューリングに影響を与えるだけでなく、他のテクノロジーにも当てはまる可能性があります。いかなる場合でも JVM を実行し続けるには、プロパティ spring.main.keep-alive を true に設定することをお勧めします。これにより、すべてのスレッドが仮想スレッドであっても、JVM は確実に存続します。