このセクションでは、Spring Boot の詳細について説明します。ここでは、使用およびカスタマイズしたい主な機能について学習できます。"入門" セクションと "Spring Boot での開発" セクションを、まだ読んでいない場合は、確認して基本を十分に理解しましょう。

1. SpringApplication

SpringApplication クラスは、main() メソッドから開始される Spring アプリケーションをブートストラップする便利な方法を提供します。多くの場合、次の例に示すように、静的 SpringApplication.run メソッドに委譲できます。

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

アプリケーションが起動すると、次のような出力が表示されるはずです。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::               (v3.2.10)

2024-09-19T06:16:30.256Z  INFO 108309 --- [           main] o.s.b.d.f.logexample.MyApplication       : Starting MyApplication using Java 17.0.12 with PID 108309 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
2024-09-19T06:16:30.307Z  INFO 108309 --- [           main] o.s.b.d.f.logexample.MyApplication       : No active profile set, falling back to 1 default profile: "default"
2024-09-19T06:16:36.037Z  INFO 108309 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2024-09-19T06:16:36.147Z  INFO 108309 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-09-19T06:16:36.147Z  INFO 108309 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.30]
2024-09-19T06:16:36.546Z  INFO 108309 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-09-19T06:16:36.563Z  INFO 108309 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 5880 ms
2024-09-19T06:16:39.130Z  INFO 108309 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path ''
2024-09-19T06:16:39.200Z  INFO 108309 --- [           main] o.s.b.d.f.logexample.MyApplication       : Started MyApplication in 11.32 seconds (process running for 12.838)

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

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

1.1. 起動失敗

アプリケーションの起動に失敗した場合、登録された 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 実装を提供します。独自の実装を追加できます。

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

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

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

1.2. 遅延初期化

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

遅延初期化の欠点は、アプリケーションの問題の発見を遅らせる可能性があることです。誤って構成された Bean が遅延初期化された場合、起動時に障害は発生せず、Bean が初期化されたときにのみ問題が明らかになります。また、JVM に、起動時に初期化される Bean だけでなく、アプリケーションのすべての Bean を収容するのに十分なメモリがあることを確認する必要があります。これらの理由により、遅延初期化はデフォルトでは有効になっていないため、遅延初期化を有効にする前に JVM のヒープサイズの微調整を行うことをお勧めします。

遅延初期化は、SpringApplicationBuilder の lazyInitialization メソッドまたは SpringApplication の setLazyInitialization メソッドを使用してプログラムで有効にできます。または、次の例に示すように、spring.main.lazy-initialization プロパティを使用して有効にすることもできます。

Properties
spring.main.lazy-initialization=true
Yaml
spring:
  main:
    lazy-initialization: true
残りのアプリケーションで遅延初期化を使用しているときに特定の Bean の遅延初期化を無効にする場合は、@Lazy(false) アノテーションを使用して遅延属性を明示的に false に設定できます。

1.3. バナーのカスタマイズ

起動時に出力されるバナーは、クラスパスに 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.2.10.

${spring-boot.formatted-version}

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

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

Where NAME is the name of an ANSI escape code. See AnsiPropertySource [GitHub] (英語) 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. バナープロパティが初期化されます。

1.4. SpringApplication のカスタマイズ

SpringApplication のデフォルトが好みに合わない場合は、代わりにローカルインスタンスを作成してカスタマイズできます。例: バナーをオフにするには、次のように記述できます。

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

}
Kotlin
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 を参照してください。

1.5. Fluent Builder API

ApplicationContext 階層(親 / 子関連を持つ複数のコンテキスト)を構築する必要がある場合、または「流れるような」ビルダー API を使用する場合は、SpringApplicationBuilder を使用できます。

SpringApplicationBuilder を使用すると、チェーンで複数のメソッド呼び出しを行うことができ、次の例に示すように、階層を作成できる parent および child メソッドが含まれます。

Java
new SpringApplicationBuilder().sources(Parent.class)
    .child(Application.class)
    .bannerMode(Banner.Mode.OFF)
    .run(args);
Kotlin
SpringApplicationBuilder()
    .sources(Parent::class.java)
    .child(Application::class.java)
    .bannerMode(Banner.Mode.OFF)
    .run(*args)
ApplicationContext 階層を作成する場合、いくつかの制限があります。例: Web コンポーネントは子コンテキスト内に含まれている必要があり、同じ Environment が親コンテキストと子コンテキストの両方に使用されます。詳細については、SpringApplicationBuilder Javadoc を参照してください。

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

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

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

1.6.1. 活性状態

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

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

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

1.6.2. 準備状態

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

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

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

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

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

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

Java
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
            }
        }
    }

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

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

}

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

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 を使用して注入できます。

1.8. 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) を呼び出すことが望ましい場合がよくあります。

1.9. アプリケーション引数へのアクセス

SpringApplication.run(…​) に渡されたアプリケーション引数にアクセスする必要がある場合は、org.springframework.boot.ApplicationArguments Bean を注入できます。ApplicationArguments インターフェースは、次の例に示すように、未加工の String[] 引数と解析された option および non-option 引数の両方へのアクセスを提供します。

Java
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"]
    }

}
Kotlin
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 アノテーションを使用して、単一のアプリケーション引数を注入することもできます。

1.10. ApplicationRunner または CommandLineRunner の使用

SpringApplication の起動後に特定のコードを実行する必要がある場合は、ApplicationRunner または CommandLineRunner インターフェースを実装できます。両方のインターフェースは同じように機能し、SpringApplication.run(…​) が完了する直前に呼び出される単一の run メソッドを提供します。

この契約は、アプリケーションの起動後、トラフィックの受け入れを開始する前に実行する必要があるタスクに適しています。

CommandLineRunner インターフェースはアプリケーションの引数へのアクセスを文字列配列として提供しますが、ApplicationRunner は前述の ApplicationArguments インターフェースを使用します。次の例は、run メソッドを使用した CommandLineRunner を示しています。

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

@Component
public class MyCommandLineRunner implements CommandLineRunner {

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

}
Kotlin
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 アノテーションを使用できます。

1.11. アプリケーション終了

各 SpringApplication はシャットダウンフックを JVM に登録して、ApplicationContext が終了時に正常に閉じるようにします。すべての標準 Spring ライフサイクルコールバック(DisposableBean インターフェースや @PreDestroy アノテーションなど)を使用できます。

さらに、Bean は、SpringApplication.exit() が呼び出されたときに特定の終了コードを返したい場合、org.springframework.boot.ExitCodeGenerator インターフェースを実装できます。次の例に示すように、この終了コードを System.exit() に渡して、ステータスコードとして返すことができます。

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

}
Kotlin
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 アノテーションを使用します。

1.12. 管理機能

spring.application.admin.enabled プロパティを指定することにより、アプリケーションの管理関連機能を有効にすることができます。これにより、プラットフォーム MBeanServerSpringApplicationAdminMXBean [GitHub] (英語) が公開されます。この機能を使用して、Spring Boot アプリケーションをリモートで管理できます。この機能は、サービスラッパーの実装にも役立ちます。

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

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

アプリケーションの起動時に、SpringApplication と ApplicationContext は、アプリケーションのライフサイクル、Bean のライフサイクル、さらにはアプリケーションイベントの処理に関連する多くのタスクを実行します。ApplicationStartup (Javadoc) を使用すると、Spring Framework を使用すると、StartupStep オブジェクトを使用してアプリケーションの起動シーケンスを追跡できます。このデータは、プロファイリングの目的で、または単にアプリケーションの起動プロセスをよりよく理解するために収集できます。

SpringApplication インスタンスをセットアップするときに、ApplicationStartup 実装を選択できます。例: BufferingApplicationStartup を使用するには、次のように記述できます。

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

}
Kotlin
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 エンドポイント (英語) を公開するように構成することもできます。

1.14. 仮想スレッド

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

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

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

2. 環境別の設定切り替え

Spring Boot を使用すると、異なる環境で同じアプリケーションコードを操作できるように、設定を外部化したり、切り替えたりすることができます。Java プロパティファイル、YAML ファイル、環境変数、コマンドライン引数など、さまざまな外部設定ソースを使用できます。

プロパティ値は、@Value アノテーションを使用して直接 Bean に注入したり、Spring の Environment 抽象化を通じてアクセスしたり、@ConfigurationProperties を通じて構造化オブジェクトにバインドしたりできます。

Spring Boot は、値を適切にオーバーライドできるように設計された、非常に特殊な PropertySource 順序を使用します。後のプロパティソースは、以前のもので定義された値をオーバーライドできます。ソースは次の順序で考慮されます。

  1. デフォルトのプロパティ(SpringApplication.setDefaultProperties の設定により指定されます)。

  2. @Configuration クラスの @PropertySource (Javadoc) アノテーション。このようなプロパティソースは、アプリケーションコンテキストがリフレッシュされるまで Environment に追加されないことに注意してください。これは、リフレッシュが始まる前に読み込まれる logging.* や spring.main.* などの特定のプロパティを設定するには遅すぎます。

  3. 構成データ(application.properties ファイルなど)。

  4. random.* のみにプロパティを持つ RandomValuePropertySource

  5. OS 環境変数。

  6. Java システムプロパティ(System.getProperties())。

  7. java:comp/env からの JNDI 属性。

  8. ServletContext 初期化パラメーター。

  9. ServletConfig 初期化パラメーター。

  10. SPRING_APPLICATION_JSON のプロパティ(環境変数またはシステムプロパティに埋め込まれたインライン JSON)。

  11. コマンドライン引数。

  12. テストの properties 属性。@SpringBootTest (Javadoc) およびアプリケーションの特定のスライスをテストするためのテストアノテーションで利用可能。

  13. テスト内の @DynamicPropertySource (Javadoc) アノテーション。

  14. テストに関する @TestPropertySource (Javadoc) アノテーション。

  15. devtools がアクティブな場合、$HOME/.config/spring-boot ディレクトリの Devtools グローバル設定プロパティ

構成データファイルは、次の順序で考慮されます。

  1. jar(application.properties および YAML バリアント)内にパッケージ化されたアプリケーションプロパティ

  2. jar(application-{profile}.properties および YAML バリアント)内にパッケージ化されたプロファイル固有のアプリケーションプロパティ

  3. パッケージ化された jar 以外のアプリケーションプロパティapplication.properties および YAML バリアント)。

  4. パッケージ化された jar 以外のプロファイル固有のアプリケーションプロパティapplication-{profile}.properties および YAML バリアント)。

アプリケーション全体で 1 つの形式を使用することをお勧めします。.properties 形式と YAML 形式の両方の構成ファイルが同じ場所にある場合は、.properties が優先されます。
システムプロパティではなく環境変数を使用する場合、ほとんどのオペレーティングシステムはピリオドで区切られたキー名を許可しませんが、代わりにアンダースコアを使用できます(たとえば、spring.config.name の代わりに SPRING_CONFIG_NAME)。詳細については、環境変数からのバインディングを参照してください。
アプリケーションがサーブレットコンテナーまたはアプリケーションサーバーで実行されている場合は、環境変数やシステムプロパティの代わりに、または環境変数やシステムプロパティの代わりに、JNDI プロパティ(java:comp/env 内)またはサーブレットコンテキスト初期化パラメーターを使用できます。

具体例を提供するために、次の例に示すように、name プロパティを使用する @Component を開発するとします。

Java
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    @Value("${name}")
    private String name;

    // ...

}
Kotlin
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component

@Component
class MyBean {

    @Value("\${name}")
    private val name: String? = null

    // ...

}

アプリケーションのクラスパス(たとえば、jar 内)に、name の適切なデフォルトのプロパティ値を提供する application.properties ファイルを含めることができます。新しい環境で実行する場合、name をオーバーライドする jar の外部で application.properties ファイルを提供できます。1 回限りのテストでは、特定のコマンドラインスイッチ(たとえば java -jar app.jar --name="Spring")で起動できます。

env および configprops エンドポイントは、プロパティに特定の値がある理由を判別できます。これらの 2 つのエンドポイントを使用して、予期しないプロパティ値を診断できます。詳細については、"本番対応機能" セクションを参照してください。

2.1. コマンドラインプロパティへのアクセス

デフォルトでは、SpringApplication はコマンドラインオプション引数(つまり、--server.port=9000 などの -- で始まる引数)を property に変換し、Spring Environment に追加します。前述のように、コマンドラインプロパティは常にファイルベースのプロパティソースよりも優先されます。

コマンドラインプロパティを Environment に追加したくない場合は、SpringApplication.setAddCommandLineProperties(false) を使用して無効にすることができます。

2.2. JSON アプリケーションのプロパティ

多くの場合、環境変数とシステムプロパティには制限があり、一部のプロパティ名は使用できません。これを支援するために、Spring Boot ではプロパティのブロックを単一の JSON 構造にエンコードできます。

アプリケーションが起動すると、spring.application.json または SPRING_APPLICATION_JSON プロパティが解析され、Environment に追加されます。

例: SPRING_APPLICATION_JSON プロパティは、環境変数として UN*X シェルのコマンドラインで指定できます。

$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar

上記の例では、Spring Environment の my.name=test になります。

同じ JSON をシステムプロパティとして提供することもできます。

$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar

または、コマンドライン引数を使用して JSON を提供することもできます。

$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'

従来のアプリケーションサーバーにデプロイする場合は、java:comp/env/spring.application.json という名前の JNDI 変数を使用することもできます。

JSON からの null 値が結果のプロパティソースに追加されますが、PropertySourcesPropertyResolver は null プロパティを欠損値として扱います。これは、JSON が null 値を持つ低次のプロパティソースからのプロパティをオーバーライドできないことを意味します。

2.3. 外部アプリケーションプロパティ

Spring Boot は、アプリケーションの起動時に、次の場所から application.properties ファイルと application.yaml ファイルを自動的に検索してロードします。

  1. クラスパスから

    1. クラスパスのルート

    2. クラスパス /config パッケージ

  2. カレントディレクトリから

    1. 現在のディレクトリ

    2. 現在のディレクトリの config/ サブディレクトリ

    3. config/ サブディレクトリの直接の子ディレクトリ

リストは優先順位で並べられます(下位の項目の値が上位の項目の値を上書きします)。ロードされたファイルのドキュメントは、PropertySources として Spring Environment に追加されます。

構成ファイル名として application が気に入らない場合は、spring.config.name 環境プロパティを指定して別のファイル名に切り替えることができます。例: myproject.properties および myproject.yaml ファイルを検索するには、次のようにアプリケーションを実行できます。

$ java -jar myproject.jar --spring.config.name=myproject

spring.config.location 環境プロパティを使用して、明示的な場所を参照することもできます。このプロパティは、チェックする 1 つ以上の場所のコンマ区切りリストを受け入れます。

次の例は、2 つの異なるファイルを指定する方法を示しています。

$ java -jar myproject.jar --spring.config.location=\
    optional:classpath:/default.properties,\
    optional:classpath:/override.properties
場所がオプションであり、存在しなくてもかまわない場合は、プレフィックス optional: を使用します。
spring.config.namespring.config.locationspring.config.additional-location は、ロードする必要のあるファイルを決定するために非常に早い段階で使用されます。これらは、環境プロパティ(通常、OS 環境変数、システムプロパティ、コマンドライン引数)として定義する必要があります。

spring.config.location に(ファイルではなく)ディレクトリが含まれている場合、/ で終わる必要があります。実行時に、ロードされる前に spring.config.name から生成された名前が追加されます。spring.config.location で指定されたファイルは直接インポートされます。

ディレクトリとファイルの場所の両方の値も展開され、プロファイル固有のファイルをチェックします。例: classpath:myconfig.properties の spring.config.location がある場合は、適切な classpath:myconfig-<profile>.properties ファイルもロードされていることがわかります。

ほとんどの場合、追加する各 spring.config.location アイテムは単一のファイルまたはディレクトリを参照します。場所は定義された順序で処理され、後のものは前のものの値を上書きできます。

複雑な場所の設定があり、プロファイル固有の構成ファイルを使用している場合は、Spring Boot がグループ化する方法を認識できるように、さらにヒントを提供する必要がある場合があります。ロケーショングループは、すべて同じレベルと見なされるロケーションのコレクションです。例: すべてのクラスパスの場所をグループ化し、次にすべての外部の場所をグループ化することができます。地域グループ内のアイテムは ; で区切る必要があります。詳細については、"プロファイル固有のファイル" セクションの例を参照してください。

spring.config.location を使用して構成された場所は、デフォルトの場所を置き換えます。例: spring.config.location が値 optional:classpath:/custom-config/,optional:file:./custom-config/ で構成されている場合、考慮される場所の完全なセットは次のとおりです。

  1. optional:classpath:custom-config/

  2. optional:file:./custom-config/

場所を置き換えるのではなく、場所を追加したい場合は、spring.config.additional-location を使用できます。追加の場所からロードされたプロパティは、デフォルトの場所のプロパティを上書きできます。例: spring.config.additional-location が値 optional:classpath:/custom-config/,optional:file:./custom-config/ で構成されている場合、考慮される場所の完全なセットは次のとおりです。

  1. optional:classpath:/;optional:classpath:/config/

  2. optional:file:./;optional:file:./config/;optional:file:./config/*/

  3. optional:classpath:custom-config/

  4. optional:file:./custom-config/

この検索順序により、ある構成ファイルでデフォルト値を指定し、別の構成ファイルでそれらの値を選択的にオーバーライドできます。デフォルトの場所の 1 つで、application.properties (または spring.config.name で選択した他のベース名)でアプリケーションのデフォルト値を提供できます。これらのデフォルト値は、カスタムロケーションのいずれかにある別のファイルで実行時にオーバーライドできます。

2.3.1. オプションの場所

デフォルトでは、指定された構成データの場所が存在しない場合、Spring Boot は ConfigDataLocationNotFoundException をスローし、アプリケーションは起動しません。

場所を指定したいが、常に存在していなくてもかまわない場合は、optional: プレフィックスを使用できます。このプレフィックスは、spring.config.location プロパティと spring.config.additional-location プロパティ、および spring.config.import 宣言で使用できます。

例: optional:file:./myconfig.properties の spring.config.import 値を使用すると、myconfig.properties ファイルが欠落している場合でもアプリケーションを起動できます。

すべての ConfigDataLocationNotFoundExceptions を無視して、常にアプリケーションを起動し続ける場合は、spring.config.on-not-found プロパティを使用できます。SpringApplication.setDefaultProperties(…​) を使用するか、システム / 環境変数を使用して、値を ignore に設定します。

2.3.2. ワイルドカードの場所

構成ファイルの場所に最後のパスセグメントの * 文字が含まれている場合、ワイルドカードの場所と見なされます。構成がロードされるとワイルドカードが展開されるため、即時サブディレクトリもチェックされます。ワイルドカードの場所は、構成プロパティのソースが複数ある場合の Kubernetes などの環境で特に役立ちます。

例: Redis 構成と MySQL 構成がある場合は、これら 2 つの構成を別々に保持し、両方が application.properties ファイルに存在する必要がある場合があります。これにより、/config/redis/application.properties や /config/mysql/application.properties などの異なる場所に 2 つの別々の application.properties ファイルがマウントされる可能性があります。このような場合、ワイルドカードの場所が config/*/ の場合、両方のファイルが処理されます。

デフォルトでは、Spring Boot はデフォルトの検索場所に config/*/ を含みます。これは、jar の外部にある /config ディレクトリのすべてのサブディレクトリが検索されることを意味します。

spring.config.location および spring.config.additional-location プロパティを使用して、ワイルドカードの場所を自分で使用できます。

ワイルドカードの場所には、* が 1 つだけ含まれ、ディレクトリである検索場所の場合は */ で終わり、ファイルである検索場所の場合は */<filename> で終わる必要があります。ワイルドカードを使用した場所は、ファイル名の絶対パスに基づいてアルファベット順にソートされます。
ワイルドカードの場所は、外部ディレクトリでのみ機能します。classpath: の場所ではワイルドカードを使用できません。

2.3.3. プロファイル固有のファイル

application プロパティファイルだけでなく、Spring Boot は、命名規則 application-{profile} を使用してプロファイル固有のファイルをロードしようとします。例: アプリケーションが prod という名前のプロファイルをアクティブ化し、YAML ファイルを使用する場合、application.yaml と application-prod.yaml の両方が考慮されます。

プロファイル固有のプロパティは、標準の application.properties と同じ場所から読み込まれ、プロファイル固有のファイルは常に非特定のファイルを上書きします。複数のプロファイルが指定されている場合は、ラストウィン戦略が適用されます。例: プロファイル prod,live が spring.profiles.active プロパティで指定されている場合、application-prod.properties の値は application-live.properties の値で上書きできます。

ラストウィン戦略は、ロケーショングループレベルで適用されます。classpath:/cfg/,classpath:/ext/ の spring.config.location には、classpath:/cfg/;classpath:/ext/ と同じオーバーライドルールはありません。

例: 上記の prod,live の例を続けると、次のファイルがある可能性があります。

/cfg
  application-live.properties
/ext
  application-live.properties
  application-prod.properties

classpath:/cfg/,classpath:/ext/ の spring.config.location がある場合、すべての /ext ファイルの前にすべての /cfg ファイルを処理します。

  1. /cfg/application-live.properties

  2. /ext/application-prod.properties

  3. /ext/application-live.properties

代わりに classpath:/cfg/;classpath:/ext/ がある場合 (; 区切り文字を使用)、/cfg と /ext を同じレベルで処理します。

  1. /ext/application-prod.properties

  2. /cfg/application-live.properties

  3. /ext/application-live.properties

Environment には、アクティブなプロファイルが設定されていない場合に使用される一連のデフォルトプロファイル(デフォルトでは [default])があります。つまり、プロファイルが明示的にアクティブ化されていない場合、application-default のプロパティが考慮されます。

プロパティファイルは一度だけロードされます。プロファイル固有のプロパティファイルをすでに直接インポートしている場合は、2 回目にインポートされることはありません。

2.3.4. 追加データのインポート

アプリケーションプロパティは、spring.config.import プロパティを使用して、他の場所からさらに構成データをインポートできます。インポートは、検出されたときに処理され、インポートを宣言するドキュメントのすぐ下に挿入された追加のドキュメントとして扱われます。

例: クラスパス application.properties ファイルに次のものがある場合があります。

Properties
spring.application.name=myapp
spring.config.import=optional:file:./dev.properties
Yaml
spring:
  application:
    name: "myapp"
  config:
    import: "optional:file:./dev.properties"

これにより、現在のディレクトリに dev.properties ファイルがインポートされます(そのようなファイルが存在する場合)。インポートされた dev.properties からの値は、インポートをトリガーしたファイルよりも優先されます。上記の例では、dev.properties は spring.application.name を別の値に再定義できます。

インポートは、宣言された回数に関係なく、一度だけインポートされます。インポートが properties/yaml ファイル内の単一のドキュメント内で定義される順序は重要ではありません。たとえば、以下の 2 つの例では同じ結果が得られます。

Properties
spring.config.import=my.properties
my.property=value
Yaml
spring:
  config:
    import: "my.properties"
my:
  property: "value"
Properties
my.property=value
spring.config.import=my.properties
Yaml
my:
  property: "value"
spring:
  config:
    import: "my.properties"

上記の両方の例で、my.properties ファイルの値は、インポートをトリガーしたファイルよりも優先されます。

1 つの spring.config.import キーで複数の場所を指定できます。場所は、定義された順序で処理され、後のインポートが優先されます。

必要に応じて、プロファイル固有のバリアントもインポートの対象と見なされます。上記の例では、my.properties と my-<profile>.properties バリアントの両方をインポートします。

Spring Boot には、さまざまな異なるロケーションアドレスをサポートできるプラグ可能な API が含まれています。デフォルトでは、Java プロパティ、YAML、「構成ツリー」をインポートできます。

サードパーティの jar は、追加のテクノロジのサポートを提供できます (ファイルがローカルである必要はありません)。例: 構成データが Consul、Apache ZooKeeper、Netflix Archaius などの外部ストアから取得されることが考えられます。

独自の場所をサポートする場合は、org.springframework.boot.context.config パッケージの ConfigDataLocationResolver クラスと ConfigDataLoader クラスを参照してください。

2.3.5. 拡張機能のないファイルのインポート

一部のクラウドプラットフォームは、ボリュームにマウントされたファイルにファイル拡張子を追加できません。これらの拡張子のないファイルをインポートするには、Spring Boot にヒントを与えて、ロードする方法を認識させる必要があります。これを行うには、角括弧に拡張ヒントを配置します。

例: yaml としてインポートしたい /etc/config/myconfig ファイルがあるとします。以下を使用して、application.properties からインポートできます。

Properties
spring.config.import=file:/etc/config/myconfig[.yaml]
Yaml
spring:
  config:
    import: "file:/etc/config/myconfig[.yaml]"

2.3.6. 構成ツリーの使用

クラウドプラットフォーム(Kubernetes など)でアプリケーションを実行する場合、プラットフォームが提供する構成値を読み取る必要があることがよくあります。このような目的で環境変数を使用することは珍しくありませんが、特に値を秘密にしておくことになっている場合、これには欠点があります。

環境変数の代わりに、多くのクラウドプラットフォームで、構成をマウントされたデータボリュームにマッピングできるようになりました。例: Kubernetes は ConfigMaps (英語) Secrets (英語) の両方をボリュームマウントできます。

使用できる一般的なボリュームマウントパターンは 2 つあります。

  1. 1 つのファイルには、プロパティの完全なセットが含まれています(通常は YAML として記述されます)。

  2. 複数のファイルがディレクトリツリーに書き込まれ、ファイル名が「キー」になり、内容が「値」になります。

最初のケースでは、上記のように spring.config.import を使用して YAML またはプロパティファイルを直接インポートできます。2 番目のケースでは、configtree: プレフィックスを使用して、すべてのファイルをプロパティとして公開する必要があることを Spring Boot が認識できるようにする必要があります。

例として、Kubernetes が次のボリュームをマウントしたと想像してみましょう。

etc/
  config/
    myapp/
      username
      password

username ファイルの内容は構成値になり、password の内容は秘密になります。

これらのプロパティをインポートするには、application.properties または application.yaml ファイルに以下を追加します。

Properties
spring.config.import=optional:configtree:/etc/config/
Yaml
spring:
  config:
    import: "optional:configtree:/etc/config/"

その後、通常の方法で Environment から myapp.username および myapp.password プロパティにアクセスまたは挿入できます。

構成ツリーのフォルダーとファイルの名前がプロパティ名を形成します。上の例では、username および password としてプロパティにアクセスするには、spring.config.import を optional:configtree:/etc/config/myapp に設定します。
ドット表記のファイル名も正しくマッピングされます。例: 上記の例では、/etc/config の myapp.username という名前のファイルは、Environment の myapp.username プロパティになります。
構成ツリーの値は、予想される内容に応じて、文字列 String 型と byte[] 型の両方にバインドできます。

同じ親フォルダーからインポートする複数の構成ツリーがある場合は、ワイルドカードショートカットを使用できます。/*/ で終わる configtree: の場所は、すべての直接の子を構成ツリーとしてインポートします。非ワイルドカードインポートと同様に、各構成ツリーのフォルダーとファイルの名前がプロパティ名を形成します。

例: 次のボリュームがある場合:

etc/
  config/
    dbconfig/
      db/
        username
        password
    mqconfig/
      mq/
        username
        password

インポート場所として configtree:/etc/config/*/ を使用できます。

Properties
spring.config.import=optional:configtree:/etc/config/*/
Yaml
spring:
  config:
    import: "optional:configtree:/etc/config/*/"

これにより、db.usernamedb.passwordmq.usernamemq.password プロパティが追加されます。

ワイルドカードを使用してロードされたディレクトリは、アルファベット順にソートされます。別のオーダーが必要な場合は、各場所を個別のインポートとしてリストする必要があります

構成ツリーは、Docker シークレットにも使用できます。Docker スウォームサービスにシークレットへのアクセスが許可されると、シークレットはコンテナーにマウントされます。例: db.password という名前のシークレットが /run/secrets/ の場所にマウントされている場合、以下を使用して db.password を Spring 環境で使用可能にすることができます。

Properties
spring.config.import=optional:configtree:/run/secrets/
Yaml
spring:
  config:
    import: "optional:configtree:/run/secrets/"

2.3.7. プロパティプレースホルダー

application.properties および application.yaml の値は、使用時に既存の Environment でフィルタリングされるため、以前に定義された値(たとえば、システムプロパティまたは環境変数から)を参照することができます。標準の ${name} プロパティ - プレースホルダー構文は、値内のどこでも使用できます。プロパティプレースホルダーは、: を使用してデフォルト値を指定し、デフォルト値をプロパティ名から分離することもできます(例: ${name:default})。

次の例では、デフォルトがある場合とない場合のプレースホルダーの使用を示しています。

Properties
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
Yaml
app:
  name: "MyApp"
  description: "${app.name} is a Spring Boot application written by ${username:Unknown}"

username プロパティが他の場所に設定されていないと仮定すると、app.description の値は MyApp is a Spring Boot application written by Unknown になります。

プレースホルダー内のプロパティ名は、常に正規形(小文字のみを使用する kebab-case)を使用して参照する必要があります。これにより、Spring Boot は、@ConfigurationPropertiesバインドを緩和した場合と同じロジックを使用できるようになります。

例: ${demo.item-price} は、application.properties ファイルから demo.item-price および demo.itemPrice フォームを取得し、システム環境から DEMO_ITEMPRICE を取得します。代わりに ${demo.itemPrice} を使用した場合、demo.item-price および DEMO_ITEMPRICE は考慮されません。

この手法を使用して、既存の Spring Boot プロパティの「短い」バリアントを作成することもできます。詳細については、howto.html使い方を参照してください。

2.3.8. マルチドキュメントファイルの操作

Spring Boot を使用すると、単一の物理ファイルを複数の論理ドキュメントに分割し、それぞれを個別に追加できます。ドキュメントは上から下に順番に処理されます。後のドキュメントは、前のドキュメントで定義されたプロパティを上書きできます。

application.yaml ファイルの場合、標準の YAML マルチドキュメント構文が使用されます。3 つの連続するハイフンは、1 つのドキュメントの終わりと、次のドキュメントの始まりを表します。

例: 次のファイルには 2 つの論理ドキュメントがあります。

spring:
  application:
    name: "MyApp"
---
spring:
  application:
    name: "MyCloudApp"
  config:
    activate:
      on-cloud-platform: "kubernetes"

application.properties ファイルの場合、特別な #--- または !--- コメントを使用してドキュメントの分割をマークします。

spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
プロパティファイルの区切り記号には、先頭に空白を入れてはならず、正確に 3 つのハイフン文字を含める必要があります。セパレータの直前と直後の行は、同じコメントプレフィックスであってはなりません。
マルチドキュメントプロパティファイルは、spring.config.activate.on-profile などのアクティベーションプロパティと組み合わせて使用されることがよくあります。詳細については、次のセクションを参照してください。
マルチドキュメントプロパティファイルは、@PropertySource または @TestPropertySource アノテーションを使用してロードすることはできません。

2.3.9. アクティベーションプロパティ

特定の条件が満たされた場合にのみ、特定のプロパティのセットをアクティブ化すると便利な場合があります。例: 特定のプロファイルがアクティブな場合にのみ関連するプロパティがある場合があります。

spring.config.activate.* を使用して、プロパティドキュメントを条件付きでアクティブ化できます。

次のアクティベーションプロパティを使用できます。

表 2: アクティベーションプロパティ
プロパティ メモ

on-profile

ドキュメントをアクティブにするために一致する必要があるプロファイル式。

on-cloud-platform

ドキュメントをアクティブにするために検出する必要がある CloudPlatform

例: 以下は、2 番目のドキュメントが Kubernetes で実行されている場合、および "prod" プロファイルまたは "staging" プロファイルのいずれかがアクティブである場合にのみアクティブになることを指定します。

Properties
myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set
Yaml
myprop:
  "always-set"
---
spring:
  config:
    activate:
      on-cloud-platform: "kubernetes"
      on-profile: "prod | staging"
myotherprop: "sometimes-set"

2.4. 暗号化プロパティ

Spring Boot は、プロパティ値を暗号化するための組み込みサポートを提供しませんが、Spring Environment に含まれる値を変更するために必要なフックポイントを提供します。EnvironmentPostProcessor インターフェースを使用すると、アプリケーションの開始前に Environment を操作できます。詳細については、howto.html を参照してください。

クレデンシャルとパスワードを安全に保存する方法が必要な場合、Spring Cloud Vault (英語) プロジェクトは、外部化された設定を HashiCorp Vault (英語) に保存するためのサポートを提供します。

2.5. YAML の操作

YAML (英語) は JSON のスーパーセットであるため、階層構成データを指定するための便利な形式です。SpringApplication クラスは、クラスパスに SnakeYAML [GitHub] (英語) ライブラリがある場合は常に、プロパティの代替として YAML を自動的にサポートします。

「スターター」を使用すると、spring-boot-starter によって SnakeYAML が自動的に提供されます。

2.5.1. YAML をプロパティにマッピングする

YAML ドキュメントは、階層形式から Spring Environment で使用できるフラットな構造に変換する必要があります。例: 次の YAML ドキュメントを検討してください:

environments:
  dev:
    url: "https://dev.example.com"
    name: "Developer Setup"
  prod:
    url: "https://another.example.com"
    name: "My Cool App"

Environment からこれらのプロパティにアクセスするために、これらは次のようにフラット化されます。

environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

同様に、YAML リストもフラット化する必要があります。これらは、[index] デリファレンスを使用したプロパティキーとして表されます。例: 次の YAML を検討してください:

my:
 servers:
 - "dev.example.com"
 - "another.example.com"

前述の例は、次のプロパティに変換されます。

my.servers[0]=dev.example.com
my.servers[1]=another.example.com
[index] 表記を使用するプロパティは、Spring Boot の Binder クラスを使用して Java List または Set オブジェクトにバインドできます。詳細については、以下の "型安全な構成プロパティ" セクションを参照してください。
YAML ファイルは、@PropertySource または @TestPropertySource アノテーションを使用してロードすることはできません。そのように値をロードする必要がある場合は、プロパティファイルを使用する必要があります。

2.5.2. YAML を直接読み込む

Spring Framework は、YAML ドキュメントのロードに使用できる 2 つの便利なクラスを提供します。YamlPropertiesFactoryBean は YAML を Properties としてロードし、YamlMapFactoryBean は YAML を Map としてロードします。

YAML を Spring PropertySource としてロードする場合は、YamlPropertySourceLoader クラスを使用することもできます。

2.6. ランダム値の構成

RandomValuePropertySource は、ランダムな値を挿入するのに便利です(たとえば、シークレットやテストケースに)。次の例に示すように、整数、long、uuid、文字列を生成できます。

Properties
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number-less-than-ten=${random.int(10)}
my.number-in-range=${random.int[1024,65536]}
Yaml
my:
  secret: "${random.value}"
  number: "${random.int}"
  bignumber: "${random.long}"
  uuid: "${random.uuid}"
  number-less-than-ten: "${random.int(10)}"
  number-in-range: "${random.int[1024,65536]}"

random.int* 構文は OPEN value (,max) CLOSE です。OPEN,CLOSE は任意の文字で、value,max は整数です。max が指定されている場合、value が最小値で、max が最大値(排他的)です。

2.7. システム環境プロパティの構成

Spring Boot は、環境プロパティのプレフィックスの設定をサポートしています。これは、システム環境が異なる構成要件を持つ複数の Spring Boot アプリケーションによって共有されている場合に役立ちます。システム環境プロパティのプレフィックスは、SpringApplication で直接設定できます。

例: プレフィックスを input に設定すると、remote.timeout などのプロパティもシステム環境で input.remote.timeout として解決されます。

2.8. 型安全な構成プロパティ

@Value("${property}") アノテーションを使用して構成プロパティを注入することは、特に複数のプロパティを使用している場合、またはデータが本質的に階層的である場合には、面倒な場合があります。Spring Boot は、強く型付けされた Bean がアプリケーションの構成を管理および検証できるようにするプロパティを操作する代替方法を提供します。

2.8.1. JavaBean プロパティのバインディング

次の例に示すように、標準 JavaBean プロパティを宣言する Bean をバインドすることができます。

Java
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my.service")
public class MyProperties {

    private boolean enabled;

    private InetAddress remoteAddress;

    private final Security security = new Security();

    // getters / setters...

    public boolean isEnabled() {
        return this.enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

    public void setRemoteAddress(InetAddress remoteAddress) {
        this.remoteAddress = remoteAddress;
    }

    public Security getSecurity() {
        return this.security;
    }

    public static class Security {

        private String username;

        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER"));

        // getters / setters...

        public String getUsername() {
            return this.username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

        public String getPassword() {
            return this.password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

        public List<String> getRoles() {
            return this.roles;
        }

        public void setRoles(List<String> roles) {
            this.roles = roles;
        }

    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import java.net.InetAddress

@ConfigurationProperties("my.service")
class MyProperties {

    var isEnabled = false

    var remoteAddress: InetAddress? = null

    val security = Security()

    class Security {

        var username: String? = null

        var password: String? = null

        var roles: List<String> = ArrayList(setOf("USER"))

    }

}

前述の POJO は、次のプロパティを定義します。

  • my.service.enabled、デフォルトでは false の値。

  •  String から強制変換できる型の my.service.remote-address

  • my.service.security.username、ネストされた「セキュリティ」オブジェクト。その名前はプロパティの名前によって決定されます。特に、その型はまったく使用されておらず、SecurityProperties である可能性があります。

  • my.service.security.password.

  • my.service.security.roles。デフォルトは USER である String のコレクションです。

プロパティファイル、YAML ファイル、環境変数、その他のメカニズムを介して構成された Spring Boot で使用可能な @ConfigurationProperties クラスにマップされるプロパティは、パブリック API ですが、クラス自体のアクセサー(getter/setter)を直接使用するためのものではありません。

このような配置は、デフォルトの空のコンストラクターに依存しており、getter と setter は通常必須です。これは、バインディングが Spring MVC の場合と同様に、標準の Java Bean プロパティ記述子を介して行われるためです。setter は、次の場合に省略できます。

  • マップは、初期化されている限り、getter を必要としますが、必ずしも setter を必要とするわけではありません。バインダーによって変更できるためです。

  • コレクションと配列には、インデックス(通常は YAML を使用)または単一のコンマ区切り値(プロパティ)を使用してアクセスできます。後者の場合、setter は必須です。そのような型には、常に setter を追加することをお勧めします。コレクションを初期化する場合は、不変でないことを確認してください(前の例のように)。

  • ネストされた POJO プロパティが初期化される場合(前述の例の Security フィールドのように)、setter は必要ありません。デフォルトのコンストラクターを使用して、バインダーがその場でインスタンスを作成するようにするには、setter が必要です。

プロジェクト Lombok を使用して、getter と setter を自動的に追加する人もいます。Lombok はオブジェクトをインスタンス化するためにコンテナーによって自動的に使用されるため、そのような型の特定のコンストラクターを生成しないように注意してください。

最後に、標準の Java Bean プロパティのみが考慮され、静的プロパティのバインドはサポートされていません。

2.8.2. コンストラクターのバインド

前のセクションの例は、次の例に示すように不変の方法で書き換えることができます。

Java
import java.net.InetAddress;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;

@ConfigurationProperties("my.service")
public class MyProperties {

    // fields...

    private final boolean enabled;

    private final InetAddress remoteAddress;

    private final Security security;

    public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
        this.enabled = enabled;
        this.remoteAddress = remoteAddress;
        this.security = security;
    }

    // getters...

    public boolean isEnabled() {
        return this.enabled;
    }

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

    public Security getSecurity() {
        return this.security;
    }

    public static class Security {

        // fields...

        private final String username;

        private final String password;

        private final List<String> roles;

        public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
            this.username = username;
            this.password = password;
            this.roles = roles;
        }

        // getters...

        public String getUsername() {
            return this.username;
        }

        public String getPassword() {
            return this.password;
        }

        public List<String> getRoles() {
            return this.roles;
        }

    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import java.net.InetAddress

@ConfigurationProperties("my.service")
class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
        val security: Security) {

    class Security(val username: String, val password: String,
            @param:DefaultValue("USER") val roles: List<String>)

}

この設定では、単一のパラメーター化されたコンストラクターが存在するということは、コンストラクターバインディングを使用する必要があることを意味します。つまり、バインダーは、バインドするパラメーターを持つコンストラクターを見つけます。クラスに複数のコンストラクターがある場合は、@ConstructorBinding アノテーションを使用して、コンストラクターバインディングに使用するコンストラクターを指定できます。単一のパラメーター化されたコンストラクターを持つクラスのコンストラクターバインディングをオプトアウトするには、コンストラクターに @Autowired アノテーションを付ける、または private にする必要があります。コンストラクターバインディングはレコードで使用できます。レコードに複数のコンストラクターがない限り、@ConstructorBinding を使用する必要はありません。

コンストラクターにバインドされたクラス(上記の例の Security など)のネストされたメンバーも、コンストラクターを介してバインドされます。

デフォルト値は、コンストラクターパラメーターおよびレコードコンポーネントで @DefaultValue を使用して指定できます。変換サービスは、アノテーションの String 値を欠落しているプロパティのターゲット型に強制変換するために適用されます。

前の例を参照すると、プロパティが Security にバインドされていない場合、MyProperties インスタンスには security の null 値が含まれます。プロパティがバインドされていない場合でも Security の null 以外のインスタンスを含めるには (Kotlin を使用する場合、Security の username および password パラメーターはデフォルト値を持たないため、null 可能として宣言する必要があります)、空の @DefaultValue アノテーション:

Java
public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
    this.enabled = enabled;
    this.remoteAddress = remoteAddress;
    this.security = security;
}
Kotlin
class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
        @DefaultValue val security: Security) {

    class Security(val username: String?, val password: String?,
            @param:DefaultValue("USER") val roles: List<String>)

}
コンストラクターバインディングを使用するには、@EnableConfigurationProperties または構成プロパティスキャンを使用してクラスを有効にする必要があります。通常の Spring メカニズムによって作成された Bean でコンストラクターバインディングを使用することはできません。(たとえば、@Component Bean、@Bean メソッドを使用して作成された Bean、または @Import を使用してロードされた Bean )
コンストラクターバインディングを使用するには、クラスを -parameters でコンパイルする必要があります。これは、Spring Boot の Gradle プラグインを使用する場合、または Maven と spring-boot-starter-parent を使用する場合に自動的に行われます。
java.util.Optional と @ConfigurationProperties の併用は、主に戻り値の型としての使用を目的としているためお勧めしません。そのため、構成プロパティの注入には適していません。他の型のプロパティとの一貫性を保つために、Optional プロパティを宣言し、それに値がない場合、空の Optional ではなく null がバインドされます。
my.service.import などのプロパティ名に予約キーワードを使用するには、コンストラクターパラメーターで @Name アノテーションを使用します。

2.8.3. @ConfigurationProperties アノテーション付き型の有効化

Spring Boot は、@ConfigurationProperties 型をバインドし、Bean として登録するためのインフラストラクチャを提供します。クラスごとに構成プロパティを有効にするか、コンポーネントスキャンと同様に機能する構成プロパティスキャンを有効にすることができます。

@ConfigurationProperties アノテーションが付けられたクラスは、たとえば、独自の自動構成を開発している場合や、条件付きで有効にしたい場合など、スキャンに適さない場合があります。これらの場合、@EnableConfigurationProperties アノテーションを使用して処理する型のリストを指定します。これは、次の例に示すように、@Configuration クラスで実行できます。

Java
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {

}
Kotlin
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties::class)
class MyConfiguration
Java
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("some.properties")
public class SomeProperties {

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("some.properties")
class SomeProperties

構成プロパティのスキャンを使用するには、@ConfigurationPropertiesScan アノテーションをアプリケーションに追加します。通常、@SpringBootApplication アノテーションが付けられたメインアプリケーションクラスに追加されますが、任意の @Configuration クラスに追加できます。デフォルトでは、アノテーションを宣言するクラスのパッケージからスキャンが行われます。スキャンする特定のパッケージを定義する場合は、次の例に示すように定義できます。

Java
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {

}
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationPropertiesScan

@SpringBootApplication
@ConfigurationPropertiesScan("com.example.app", "com.example.another")
class MyApplication

@ConfigurationProperties Bean が構成プロパティスキャンを使用して、または @EnableConfigurationProperties を介して登録される場合、Bean は従来の名前 <prefix>-<fqn> を持ちます。ここで、<prefix> は @ConfigurationProperties アノテーションで指定された環境キー接頭部であり、<fqn> は Bean の完全修飾名です。アノテーションにプレフィックスが含まれていない場合は、Bean の完全修飾名のみが使用されます。

com.example.app パッケージにあると仮定すると、上記の SomeProperties の例の Bean 名は some.properties-com.example.app.SomeProperties です。

@ConfigurationProperties は環境のみを扱い、特にコンテキストから他の Bean を注入しないことをお勧めします。コーナーケースの場合、setter インジェクションを使用するか、フレームワークによって提供される *Aware インターフェースのいずれか(Environment へのアクセスが必要な場合は EnvironmentAware など)を使用できます。それでもコンストラクターを使用して他の Bean を注入する場合は、構成プロパティ Bean に @Component のアノテーションを付け、JavaBean ベースのプロパティバインディングを使用する必要があります。

2.8.4. @ConfigurationProperties アノテーション付き型の使用

このスタイルの構成は、次の例に示すように、SpringApplication 外部 YAML 構成で特にうまく機能します。

my:
  service:
    remote-address: 192.168.1.1
    security:
      username: "admin"
      roles:
      - "USER"
      - "ADMIN"

@ConfigurationProperties Bean を使用するには、次の例に示すように、他の Bean と同じ方法で注入できます。

Java
import org.springframework.stereotype.Service;

@Service
public class MyService {

    private final MyProperties properties;

    public MyService(MyProperties properties) {
        this.properties = properties;
    }

    public void openConnection() {
        Server server = new Server(this.properties.getRemoteAddress());
        server.start();
        // ...
    }

    // ...

}
Kotlin
import org.springframework.stereotype.Service

@Service
class MyService(val properties: MyProperties) {

    fun openConnection() {
        val server = Server(properties.remoteAddress)
        server.start()
        // ...
    }

    // ...

}
@ConfigurationProperties を使用すると、IDE で使用できるメタデータファイルを生成して、独自のキーの自動補完を提供することもできます。詳細については、付録を参照してください。

2.8.5. サードパーティの構成

@ConfigurationProperties を使用してクラスにアノテーションを付けるだけでなく、パブリック @Bean メソッドでも使用できます。これは、コントロール外のサードパーティコンポーネントにプロパティをバインドする場合に特に役立ちます。

Environment プロパティから Bean を構成するには、次の例に示すように、@ConfigurationProperties を Bean 登録に追加します。

Java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "another")
    public AnotherComponent anotherComponent() {
        return new AnotherComponent();
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class ThirdPartyConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "another")
    fun anotherComponent(): AnotherComponent = AnotherComponent()

}

another プレフィックスで定義された JavaBean プロパティは、前述の SomeProperties の例と同様の方法で、その AnotherComponent Bean にマッピングされます。

2.8.6. 緩いバインディング

Spring Boot は、Environment プロパティを @ConfigurationProperties Bean にバインドするためにいくつかの緩和されたルールを使用しているため、Environment プロパティ名と Bean プロパティ名が完全に一致する必要はありません。これが役立つ一般的な例には、ダッシュで区切られた環境プロパティ(たとえば、context-path が contextPath にバインド)、大文字の環境プロパティ(たとえば、PORT が port にバインド)があります。

例として、次の @ConfigurationProperties クラスを検討してください。

Java
import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {

    private String firstName;

    public String getFirstName() {
        return this.firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "my.main-project.person")
class MyPersonProperties {

    var firstName: String? = null

}

上記のコードでは、次のプロパティ名をすべて使用できます。

表 3: 緩いバインディング
プロパティ メモ

my.main-project.person.first-name

Kebab ケース。.properties および YAML ファイルでの使用が推奨されます。

my.main-project.person.firstName

標準のキャメルケースの構文。

my.main-project.person.first_name

アンダースコア表記。.properties および YAML ファイルで使用される代替形式です。

MY_MAINPROJECT_PERSON_FIRSTNAME

システム環境変数を使用する場合に推奨される大文字形式。

アノテーションの prefix 値はケバブの場合(小文字で、my.main-project.person などの - で区切られている)でなければなりません
表 4: プロパティソースごとの緩いバインディングルール
プロパティソース シンプル リスト

プロパティファイル

キャメルケース、ケバブケース、アンダースコア表記

[ ] またはコンマ区切り値を使用した標準リスト構文

YAML ファイル

キャメルケース、ケバブケース、アンダースコア表記

標準の YAML リスト構文またはコンマ区切り値

環境変数

区切り文字としてアンダースコアを使用した大文字の形式(環境変数からのバインディングを参照)。

アンダースコアで囲まれた数値 ( 環境変数からのバインディングを参照してください)

システムプロパティ

キャメルケース、ケバブケース、アンダースコア表記

[ ] またはコンマ区切り値を使用した標準リスト構文

可能な場合、プロパティは my.person.first-name=Rod などの小文字のケバブ形式で保存することをお勧めします。
マップのバインド

Map プロパティにバインドする場合、元の key 値が保持されるように、特別な括弧表記を使用する必要がある場合があります。キーが [] で囲まれていない場合、英数字、-. 以外の文字はすべて削除されます。

例: 次のプロパティを Map<String,String> にバインドすることを検討してください。

Properties
my.map.[/key1]=value1
my.map.[/key2]=value2
my.map./key3=value3
Yaml
my:
  map:
    "[/key1]": "value1"
    "[/key2]": "value2"
    "/key3": "value3"
YAML ファイルの場合、キーを適切に解析するには、括弧を引用符で囲む必要があります。

上記のプロパティは、マップ内のキーとして /key1/key2key3 を使用して Map にバインドされます。スラッシュは角括弧で囲まれていなかったため、key3 から削除されました。

スカラー値にバインドする場合、. を含むキーを [] で囲む必要はありません。スカラー値には、Object を除く java.lang パッケージの列挙型とすべての型が含まれます。a.b=c を Map<String, String> にバインドすると、キーに . が保持され、エントリ {"a.b"="c"} のマップが返されます。その他の型では、key に . が含まれている場合は、括弧表記を使用する必要があります。例: a.b=c を Map<String, Object> にバインドすると、エントリ {"a"={"b"="c"}} のマップが返されますが、[a.b]=c はエントリ {"a.b"="c"} のマップが返されます。

環境変数からのバインディング

ほとんどのオペレーティングシステムでは、環境変数に使用できる名前に関する厳格なルールが適用されます。例: Linux シェル変数には、文字(a から z または A から Z)、数字(0 から 9)または下線文字(_)のみを含めることができます。慣例により、Unix シェル変数も大文字で名前が付けられます。

Spring Boot の緩いバインディングルールは、可能な限り、これらの命名制限と互換性を持つように設計されています。

正規形式のプロパティ名を環境変数名に変換するには、次のルールに従います。

  • ドット(.)をアンダースコア(_)に置き換えます。

  • ダッシュ(-)をすべて削除します。

  • 大文字に変換します。

例: 構成プロパティ spring.main.log-startup-info は SPRING_MAIN_LOGSTARTUPINFO という名前の環境変数になります。

環境変数は、オブジェクトリストにバインドするときにも使用できます。List にバインドするには、変数名で要素番号をアンダースコアで囲む必要があります。例: 構成プロパティ my.service[0].other は、MY_SERVICE_0_OTHER という名前の環境変数を使用します。

環境変数からのバインディングのサポートは、systemEnvironment プロパティソースと、名前が -systemEnvironment で終わる追加のプロパティソースに適用されます。

キャッシング

緩和バインディングでは、キャッシュを使用してパフォーマンスを向上させます。デフォルトでは、このキャッシュは不変プロパティソースにのみ適用されます。この動作をカスタマイズするには、たとえば変更可能なプロパティソースのキャッシュを有効にするには、ConfigurationPropertyCaching を使用します。

2.8.7. 複合型のマージ

リストが複数の場所で構成されている場合、オーバーライドはリスト全体を置き換えることで機能します。

例: null である name および description 属性を持つ MyPojo オブジェクトをデフォルトと想定します。次の例は、MyProperties から MyPojo オブジェクトのリストを公開します。

Java
import java.util.ArrayList;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my")
public class MyProperties {

    private final List<MyPojo> list = new ArrayList<>();

    public List<MyPojo> getList() {
        return this.list;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("my")
class MyProperties {

    val list: List<MyPojo> = ArrayList()

}

次の構成を検討してください。

Properties
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
Yaml
my:
  list:
  - name: "my name"
    description: "my description"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  list:
  - name: "my another name"

dev プロファイルがアクティブでない場合、MyProperties.list には、前に定義したように 1 つの MyPojo エントリが含まれます。ただし、dev プロファイルが有効になっている場合、list にはまだ 1 つのエントリしか含まれていません(名前が my another name で説明が null)。この構成で、2 番目の MyPojo インスタンスはリストに追加されず、アイテムはマージされません。

List が複数のプロファイルで指定されている場合、最高の優先順位を持つプロファイル(およびそのプロファイルのみ)が使用されます。次の例を考えてみましょう。

Properties
my.list[0].name=my name
my.list[0].description=my description
my.list[1].name=another name
my.list[1].description=another description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
Yaml
my:
  list:
  - name: "my name"
    description: "my description"
  - name: "another name"
    description: "another description"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  list:
  - name: "my another name"

上記の例で、dev プロファイルがアクティブである場合、MyProperties.list には 1 つの  MyPojo エントリ(名前 my another name および説明 null)が含まれます。YAML の場合、コンマ区切りリストと YAML リストの両方を使用して、リストの内容を完全にオーバーライドできます。

Map プロパティの場合、複数のソースから取得したプロパティ値とバインドできます。ただし、複数のソースの同じプロパティの場合、優先度が最も高いプロパティが使用されます。次の例は、MyProperties から Map<String, MyPojo> を公開します。

Java
import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("my")
public class MyProperties {

    private final Map<String, MyPojo> map = new LinkedHashMap<>();

    public Map<String, MyPojo> getMap() {
        return this.map;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties("my")
class MyProperties {

    val map: Map<String, MyPojo> = LinkedHashMap()

}

次の構成を検討してください。

Properties
my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
spring.config.activate.on-profile=dev
my.map.key1.name=dev name 1
my.map.key2.name=dev name 2
my.map.key2.description=dev description 2
Yaml
my:
  map:
    key1:
      name: "my name 1"
      description: "my description 1"
---
spring:
  config:
    activate:
      on-profile: "dev"
my:
  map:
    key1:
      name: "dev name 1"
    key2:
      name: "dev name 2"
      description: "dev description 2"

dev プロファイルがアクティブでない場合、MyProperties.map にはキー key1 (名前 my name 1 および説明 my description 1)を持つ 1 つのエントリが含まれます。ただし、dev プロファイルが有効になっている場合、map には、キー key1 (名前 dev name 1 および説明 my description 1)および key2 (名前 dev name 2 および説明 dev description 2)の 2 つのエントリが含まれます。

上記のマージルールは、ファイルだけでなく、すべてのプロパティソースからのプロパティに適用されます。

2.8.8. プロパティの変換

Spring Boot は、@ConfigurationProperties Bean にバインドするときに、外部アプリケーションプロパティを正しい型に強制しようとします。カスタム型の変換が必要な場合は、ConversionService Bean(conversionService という名前の Bean を使用)またはカスタムプロパティエディター(CustomEditorConfigurer Bean を使用)またはカスタム Converters (@ConfigurationPropertiesBinding としてアノテーション付けされた Bean 定義を使用)を提供できます。

この Bean はアプリケーションライフサイクルの非常に早い段階でリクエストされるため、ConversionService が使用している依存関係を必ず制限してください。通常、必要な依存関係は作成時に完全に初期化されない場合があります。構成キーの強制に不要なカスタム ConversionService の名前を変更し、@ConfigurationPropertiesBinding で修飾されたカスタムコンバーターのみに依存することができます。
時間ベースの期間変換

Spring Boot は、期間を表現するための専用サポートを備えています。java.time.Duration プロパティを公開する場合、アプリケーションプロパティで次の形式を使用できます。

  • 通常の long 表現 (@DurationUnit が指定されていない限り、デフォルトの単位としてミリ秒を使用する)

  • java.time.Duration が使用する (標準 Javadoc) 標準 ISO-8601 形式

  • 値と単位が結合された、より読みやすい形式 (10s は 10 秒を意味します)

次の例を考えてみましょう。

Java
import java.time.Duration;
import java.time.temporal.ChronoUnit;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;

@ConfigurationProperties("my")
public class MyProperties {

    @DurationUnit(ChronoUnit.SECONDS)
    private Duration sessionTimeout = Duration.ofSeconds(30);

    private Duration readTimeout = Duration.ofMillis(1000);

    // getters / setters...

    public Duration getSessionTimeout() {
        return this.sessionTimeout;
    }

    public void setSessionTimeout(Duration sessionTimeout) {
        this.sessionTimeout = sessionTimeout;
    }

    public Duration getReadTimeout() {
        return this.readTimeout;
    }

    public void setReadTimeout(Duration readTimeout) {
        this.readTimeout = readTimeout;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit

@ConfigurationProperties("my")
class MyProperties {

    @DurationUnit(ChronoUnit.SECONDS)
    var sessionTimeout = Duration.ofSeconds(30)

    var readTimeout = Duration.ofMillis(1000)

}

30 秒のセッションタイムアウトを指定するには、30PT30S30s はすべて同等です。500ms の読み取りタイムアウトは、500PT0.5S500ms のいずれかの形式で指定できます。

サポートされている任意のユニットを使用することもできます。

  • ns ナノ秒

  • us マイクロ秒

  • ms ミリ秒

  • s 秒

  • m 分

  • h 時間

  • d 日

デフォルトの単位はミリ秒であり、上記のサンプルに示すように、@DurationUnit を使用してオーバーライドできます。

コンストラクターバインディングを使用する場合は、次の例に示すように、同じプロパティを公開できます。

Java
import java.time.Duration;
import java.time.temporal.ChronoUnit;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DurationUnit;

@ConfigurationProperties("my")
public class MyProperties {

    // fields...

    private final Duration sessionTimeout;

    private final Duration readTimeout;

    public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
            @DefaultValue("1000ms") Duration readTimeout) {
        this.sessionTimeout = sessionTimeout;
        this.readTimeout = readTimeout;
    }

    // getters...

    public Duration getSessionTimeout() {
        return this.sessionTimeout;
    }

    public Duration getReadTimeout() {
        return this.readTimeout;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit

@ConfigurationProperties("my")
class MyProperties(@param:DurationUnit(ChronoUnit.SECONDS) @param:DefaultValue("30s") val sessionTimeout: Duration,
        @param:DefaultValue("1000ms") val readTimeout: Duration)
Long プロパティをアップグレードする場合、ミリ秒でない場合は必ず単位を定義してください(@DurationUnit を使用)。そうすることで、より豊富なフォーマットをサポートしながら、透過的なアップグレードパスが提供されます。
期間の変換

時間ベースの期間に加えて、Spring Boot は java.time.Period 型でも機能します。アプリケーションのプロパティでは、次の形式を使用できます。

  • 通常の int 表現 (@PeriodUnit が指定されていない限り、デフォルトの単位として日を使用する)

  • java.time.Period が使用する (標準 Javadoc) 標準 ISO-8601 形式

  • 値と単位のペアが結合されたより簡単な形式 (1y3d は 1 年 3 日を意味します)

次の単位は、単純な形式でサポートされています。

  • y 年

  • m 月

  • w 週

  • d 日

java.time.Period 型は実際には週数を格納しません。これは「7 日」を意味するショートカットです。
データサイズの変換

Spring Framework には、サイズをバイト単位で表す DataSize 値型があります。DataSize プロパティを公開する場合、アプリケーションプロパティで次の形式を使用できます。

  • 通常の long 表現 (@DataSizeUnit が指定されていない限り、デフォルトの単位としてバイトを使用)

  • 値と単位が結合された、より読みやすい形式 (10MB は 10 メガバイトを意味します)

次の例を考えてみましょう。

Java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

@ConfigurationProperties("my")
public class MyProperties {

    @DataSizeUnit(DataUnit.MEGABYTES)
    private DataSize bufferSize = DataSize.ofMegabytes(2);

    private DataSize sizeThreshold = DataSize.ofBytes(512);

    // getters/setters...

    public DataSize getBufferSize() {
        return this.bufferSize;
    }

    public void setBufferSize(DataSize bufferSize) {
        this.bufferSize = bufferSize;
    }

    public DataSize getSizeThreshold() {
        return this.sizeThreshold;
    }

    public void setSizeThreshold(DataSize sizeThreshold) {
        this.sizeThreshold = sizeThreshold;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit

@ConfigurationProperties("my")
class MyProperties {

    @DataSizeUnit(DataUnit.MEGABYTES)
    var bufferSize = DataSize.ofMegabytes(2)

    var sizeThreshold = DataSize.ofBytes(512)

}

10 メガバイトのバッファーサイズを指定するには、10 と 10MB は同等です。256 バイトのサイズしきい値は、256 または 256B として指定できます。

サポートされている任意のユニットを使用することもできます。

  • B バイト

  • KB キロバイト

  • MB メガバイト

  • GB ギガバイト

  • TB テラバイト

デフォルトの単位はバイトであり、上記のサンプルに示すように @DataSizeUnit を使用してオーバーライドできます。

コンストラクターバインディングを使用する場合は、次の例に示すように、同じプロパティを公開できます。

Java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;

@ConfigurationProperties("my")
public class MyProperties {

    // fields...

    private final DataSize bufferSize;

    private final DataSize sizeThreshold;

    public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
            @DefaultValue("512B") DataSize sizeThreshold) {
        this.bufferSize = bufferSize;
        this.sizeThreshold = sizeThreshold;
    }

    // getters...

    public DataSize getBufferSize() {
        return this.bufferSize;
    }

    public DataSize getSizeThreshold() {
        return this.sizeThreshold;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit

@ConfigurationProperties("my")
class MyProperties(@param:DataSizeUnit(DataUnit.MEGABYTES) @param:DefaultValue("2MB") val bufferSize: DataSize,
        @param:DefaultValue("512B") val sizeThreshold: DataSize)
Long プロパティをアップグレードする場合、バイトでない場合は必ず単位を定義してください(@DataSizeUnit を使用)。そうすることで、より豊富なフォーマットをサポートしながら、透過的なアップグレードパスが提供されます。

2.8.9. @ConfigurationProperties 検証

Spring Boot は、Spring の @Validated アノテーションが付けられている場合、@ConfigurationProperties クラスを検証しようとします。JSR-303 jakarta.validation 制約アノテーションを構成クラスで直接使用できます。これを行うには、次の例に示すように、準拠する JSR-303 実装がクラスパス上にあることを確認してから、フィールドに制約アノテーションを追加します。

Java
import java.net.InetAddress;

import jakarta.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

    @NotNull
    private InetAddress remoteAddress;

    // getters/setters...

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

    public void setRemoteAddress(InetAddress remoteAddress) {
        this.remoteAddress = remoteAddress;
    }

}
Kotlin
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress

@ConfigurationProperties("my.service")
@Validated
class MyProperties {

    var remoteAddress: @NotNull InetAddress? = null

}
@Validated を使用して構成プロパティを作成する @Bean メソッドにアノテーションを付けることにより、検証をトリガーすることもできます。

ネストされたプロパティに対して検証が常にトリガーされるようにするには、プロパティが見つからない場合でも、関連付けられたフィールドに @Valid のアノテーションを付ける必要があります。次の例は、前述の MyProperties の例に基づいています。

Java
import java.net.InetAddress;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@ConfigurationProperties("my.service")
@Validated
public class MyProperties {

    @NotNull
    private InetAddress remoteAddress;

    @Valid
    private final Security security = new Security();

    // getters/setters...

    public InetAddress getRemoteAddress() {
        return this.remoteAddress;
    }

    public void setRemoteAddress(InetAddress remoteAddress) {
        this.remoteAddress = remoteAddress;
    }

    public Security getSecurity() {
        return this.security;
    }

    public static class Security {

        @NotEmpty
        private String username;

        // getters/setters...

        public String getUsername() {
            return this.username;
        }

        public void setUsername(String username) {
            this.username = username;
        }

    }

}
Kotlin
import jakarta.validation.Valid
import jakarta.validation.constraints.NotEmpty
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress

@ConfigurationProperties("my.service")
@Validated
class MyProperties {

    var remoteAddress: @NotNull InetAddress? = null

    @Valid
    val security = Security()

    class Security {

        @NotEmpty
        var username: String? = null

    }

}

configurationPropertiesValidator という Bean 定義を作成して、カスタム Spring Validator を追加することもできます。@Bean メソッドは static として宣言する必要があります。構成プロパティバリデーターは、アプリケーションのライフサイクルの非常に早い段階で作成され、@Bean メソッドを静的として宣言すると、@Configuration クラスをインスタンス化せずに Bean を作成できます。そうすることで、早期のインスタンス化によって引き起こされる可能性のある問題を回避できます。

spring-boot-actuator モジュールには、すべての @ConfigurationProperties Bean を公開するエンドポイントが含まれています。Web ブラウザーで /actuator/configprops を指すか、同等の JMX エンドポイントを使用します。詳細については、"本番対応機能" セクションを参照してください。

2.8.10. @ConfigurationProperties 対 @Value

@Value アノテーションはコアコンテナー機能であり、型安全な構成プロパティと同じ機能を提供しません。次の表は、@ConfigurationProperties および @Value でサポートされている機能をまとめたものです。

フィーチャー @ConfigurationProperties@Value

緩いバインディング

はい

限定的 ( 以下の注を参照してください)

メタデータのサポート

はい

いいえ

SpEL evaluation

No

Yes

If you do want to use @Value, we recommend that you refer to property names using their canonical form (kebab-case using only lowercase letters). This will allow Spring Boot to use the same logic as it does when relaxed binding @ConfigurationProperties.

For example, @Value("${demo.item-price}") will pick up demo.item-price and demo.itemPrice forms from the application.properties file, as well as DEMO_ITEMPRICE from the system environment. If you used @Value("${demo.itemPrice}") instead, demo.item-price and DEMO_ITEMPRICE would not be considered.

If you define a set of configuration keys for your own components, we recommend you group them in a POJO annotated with @ConfigurationProperties. Doing so will provide you with structured, type-safe object that you can inject into your own beans.

SpEL expressions from application property files are not processed at time of parsing these files and populating the environment. However, it is possible to write a SpEL expression in @Value. If the value of a property from an application property file is a SpEL expression, it will be evaluated when consumed through @Value.

3. Profiles

Spring Profiles provide a way to segregate parts of your application configuration and make it be available only in certain environments. Any @Component, @Configuration or @ConfigurationProperties can be marked with @Profile to limit when it is loaded, as shown in the following example:

Java
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Configuration(proxyBeanMethods = false)
@Profile("production")
public class ProductionConfiguration {

    // ...

}
Kotlin
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile

@Configuration(proxyBeanMethods = false)
@Profile("production")
class ProductionConfiguration {

    // ...

}
If @ConfigurationProperties beans are registered through @EnableConfigurationProperties instead of automatic scanning, the @Profile annotation needs to be specified on the @Configuration class that has the @EnableConfigurationProperties annotation. In the case where @ConfigurationProperties are scanned, @Profile can be specified on the @ConfigurationProperties class itself.

You can use a spring.profiles.active Environment property to specify which profiles are active. You can specify the property in any of the ways described earlier in this chapter. For example, you could include it in your application.properties, as shown in the following example:

Properties
spring.profiles.active=dev,hsqldb
Yaml
spring:
  profiles:
    active: "dev,hsqldb"

You could also specify it on the command line by using the following switch: --spring.profiles.active=dev,hsqldb.

If no profile is active, a default profile is enabled. The name of the default profile is default and it can be tuned using the spring.profiles.default Environment property, as shown in the following example:

Properties
spring.profiles.default=none
Yaml
spring:
  profiles:
    default: "none"

spring.profiles.active and spring.profiles.default can only be used in non-profile-specific documents. This means they cannot be included in profile specific files or documents activated by spring.config.activate.on-profile.

For example, the second document configuration is invalid:

Properties
# this document is valid
spring.profiles.active=prod
#---
# this document is invalid
spring.config.activate.on-profile=prod
spring.profiles.active=metrics
Yaml
# this document is valid
spring:
  profiles:
    active: "prod"
---
# this document is invalid
spring:
  config:
    activate:
      on-profile: "prod"
  profiles:
    active: "metrics"

3.1. Adding Active Profiles

The spring.profiles.active property follows the same ordering rules as other properties: The highest PropertySource wins. This means that you can specify active profiles in application.properties and then replace them by using the command line switch.

Sometimes, it is useful to have properties that add to the active profiles rather than replace them. The spring.profiles.include property can be used to add active profiles on top of those activated by the spring.profiles.active property. The SpringApplication entry point also has a Java API for setting additional profiles. See the setAdditionalProfiles() method in SpringApplication (Javadoc) .

For example, when an application with the following properties is run, the common and local profiles will be activated even when it runs using the --spring.profiles.active switch:

Properties
spring.profiles.include[0]=common
spring.profiles.include[1]=local
Yaml
spring:
  profiles:
    include:
      - "common"
      - "local"
Similar to spring.profiles.active, spring.profiles.include can only be used in non-profile-specific documents. This means it cannot be included in profile specific files or documents activated by spring.config.activate.on-profile.

Profile groups, which are described in the next section can also be used to add active profiles if a given profile is active.

3.2. Profile Groups

Occasionally the profiles that you define and use in your application are too fine-grained and become cumbersome to use. For example, you might have proddb and prodmq profiles that you use to enable database and messaging features independently.

To help with this, Spring Boot lets you define profile groups. A profile group allows you to define a logical name for a related group of profiles.

For example, we can create a production group that consists of our proddb and prodmq profiles.

Properties
spring.profiles.group.production[0]=proddb
spring.profiles.group.production[1]=prodmq
Yaml
spring:
  profiles:
    group:
      production:
      - "proddb"
      - "prodmq"

Our application can now be started using --spring.profiles.active=production to activate the production, proddb and prodmq profiles in one hit.

Similar to spring.profiles.active and spring.profiles.include, spring.profiles.group can only be used in non-profile-specific documents. This means it cannot be included in profile specific files or documents activated by spring.config.activate.on-profile.

3.3. Programmatically Setting Profiles

You can programmatically set active profiles by calling SpringApplication.setAdditionalProfiles(…​) before your application runs. It is also possible to activate profiles by using Spring’s ConfigurableEnvironment interface.

3.4. Profile-specific Configuration Files

Profile-specific variants of both application.properties (or application.yaml) and files referenced through @ConfigurationProperties are considered as files and loaded. See "Profile Specific Files" for details.

4. Logging

Spring Boot uses Commons Logging [Apache] (英語) for all internal logging but leaves the underlying log implementation open. Default configurations are provided for Java Util Logging (標準 Javadoc) (英語) , Log4j2 [Apache] (英語) , and Logback (英語) . In each case, loggers are pre-configured to use console output with optional file output also available.

By default, if you use the “Starters”, Logback is used for logging. Appropriate Logback routing is also included to ensure that dependent libraries that use Java Util Logging, Commons Logging, Log4J, or SLF4J all work correctly.

There are a lot of logging frameworks available for Java. Do not worry if the above list seems confusing. Generally, you do not need to change your logging dependencies and the Spring Boot defaults work just fine.
When you deploy your application to a servlet container or application server, logging performed with the Java Util Logging API is not routed into your application’s logs. This prevents logging performed by the container or other applications that have been deployed to it from appearing in your application’s logs.

4.1. Log Format

The default log output from Spring Boot resembles the following example:

2024-09-19T06:16:15.534Z  INFO 108077 --- [myapp] [           main] o.s.b.d.f.logexample.MyApplication       : Starting MyApplication using Java 17.0.12 with PID 108077 (/opt/apps/myapp.jar started by myuser in /opt/apps/)
2024-09-19T06:16:15.541Z  INFO 108077 --- [myapp] [           main] o.s.b.d.f.logexample.MyApplication       : No active profile set, falling back to 1 default profile: "default"
2024-09-19T06:16:20.210Z  INFO 108077 --- [myapp] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8080 (http)
2024-09-19T06:16:20.276Z  INFO 108077 --- [myapp] [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2024-09-19T06:16:20.277Z  INFO 108077 --- [myapp] [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.30]
2024-09-19T06:16:20.491Z  INFO 108077 --- [myapp] [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2024-09-19T06:16:20.505Z  INFO 108077 --- [myapp] [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 4771 ms
2024-09-19T06:16:22.523Z  INFO 108077 --- [myapp] [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8080 (http) with context path ''
2024-09-19T06:16:22.668Z  INFO 108077 --- [myapp] [           main] o.s.b.d.f.logexample.MyApplication       : Started MyApplication in 8.451 seconds (process running for 9.879)

The following items are output:

  • Date and Time: Millisecond precision and easily sortable.

  • Log Level: ERROR, WARN, INFO, DEBUG, or TRACE.

  • Process ID.

  • A --- separator to distinguish the start of actual log messages.

  • Application name: Enclosed in square brackets (logged by default only if spring.application.name is set)

  • Thread name: Enclosed in square brackets (may be truncated for console output).

  • Correlation ID: If tracing is enabled (not shown in the sample above)

  • Logger name: This is usually the source class name (often abbreviated).

  • The log message.

Logback does not have a FATAL level. It is mapped to ERROR.
If you have a spring.application.name property but don’t want it logged you can set logging.include-application-name to false.

4.2. Console Output

The default log configuration echoes messages to the console as they are written. By default, ERROR-level, WARN-level, and INFO-level messages are logged. You can also enable a “debug” mode by starting your application with a --debug flag.

$ java -jar myapp.jar --debug
You can also specify debug=true in your application.properties.

When the debug mode is enabled, a selection of core loggers (embedded container, Hibernate, and Spring Boot) are configured to output more information. Enabling the debug mode does not configure your application to log all messages with DEBUG level.

Alternatively, you can enable a “trace” mode by starting your application with a --trace flag (or trace=true in your application.properties). Doing so enables trace logging for a selection of core loggers (embedded container, Hibernate schema generation, and the whole Spring portfolio).

4.2.1. Color-coded Output

If your terminal supports ANSI, color output is used to aid readability. You can set spring.output.ansi.enabled to a supported value (Javadoc) to override the auto-detection.

Color coding is configured by using the %clr conversion word. In its simplest form, the converter colors the output according to the log level, as shown in the following example:

%clr(%5p)

The following table describes the mapping of log levels to colors:

Level Color

FATAL

ERROR

WARN

INFO

DEBUG

TRACE

または、変換のオプションとして使用することにより、使用する色またはスタイルを指定できます。例: テキストを黄色にするには、次の設定を使用します。

%clr(%d{yyyy-MM-dd'T'HH:mm:ss.SSSXXX}){yellow}

次の色とスタイルがサポートされています。

  • blue

  • cyan

  • faint

  • green

  • magenta

  • red

  • yellow

4.3. ファイル出力

デフォルトでは、Spring Boot はコンソールにのみログを記録し、ログファイルに書き込みません。コンソール出力に加えてログファイルにも書き込みたい場合は、logging.file.name または logging.file.path プロパティを設定する必要があります (たとえば、application.properties で)。両方のプロパティが設定されている場合、logging.file.path は無視され、logging.file.name のみが使用されます。

次の表は、logging.* プロパティを一緒に使用する方法を示しています。

表 5: ロギングプロパティ
logging.file.namelogging.file.path 説明

(なし)

(なし)

コンソールのみのロギング。

特定のファイル (たとえば、my.log)

(なし)

logging.file.name で指定された場所に書き込みます。場所は絶対パスでも、現在のディレクトリに対する相対パスでもかまいません。

(なし)

特定のディレクトリ (たとえば、/var/log)

spring.log を logging.file.path で指定されたディレクトリに書き込みます。ディレクトリは絶対ディレクトリでも、現在のディレクトリに対する相対ディレクトリでもかまいません。

特定のファイル

特定のディレクトリ

logging.file.name で指定された場所に書き込み、logging.file.path を無視します。場所は絶対または現在のディレクトリに対する相対にすることができます。

ログファイルは 10MB に達するとローテーションし、コンソール出力と同様に、ERROR -level、WARN -level、および INFO -level メッセージがデフォルトでログに記録されます。

ロギングプロパティは、実際のロギングインフラストラクチャから独立しています。その結果、特定の構成キー(Logback の logback.configurationFile など)は spring Boot によって管理されません。

4.4. ファイルのローテーション

Logback を使用している場合は、application.properties または application.yaml ファイルを使用してログローテーション設定を微調整することができます。他のすべてのロギングシステムでは、ローテーション設定を自分で直接構成する必要があります (たとえば、Log4j2 を使用している場合は、log4j2.xml または log4j2-spring.xml ファイルを追加できます)。

次のローテーションポリシープロパティがサポートされています。

名前 説明

logging.logback.rollingpolicy.file-name-pattern

ログアーカイブの作成に使用されるファイル名パターン。

logging.logback.rollingpolicy.clean-history-on-start

アプリケーションの起動時にログアーカイブのクリーンアップが必要な場合。

logging.logback.rollingpolicy.max-file-size

アーカイブされる前のログファイルの最大サイズ。

logging.logback.rollingpolicy.total-size-cap

ログアーカイブが削除されるまでにかかる最大サイズ。

logging.logback.rollingpolicy.max-history

保持するアーカイブログファイルの最大数(デフォルトは 7)。

4.5. ログレベル

サポートされているすべてのロギングシステムでは、level が TRACE、DEBUG、INFO、WARN、ERROR、FATAL、OFF のいずれかである logging.level.<logger-name>=<level> を使用して、Spring Environment (たとえば application.properties)にロガーレベルを設定できます。root ロガーは、logging.level.root を使用して構成できます。

次の例は、application.properties の潜在的なロギング設定を示しています。

Properties
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
Yaml
logging:
  level:
    root: "warn"
    org.springframework.web: "debug"
    org.hibernate: "error"

環境変数を使用してログレベルを設定することもできます。例: LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_WEB=DEBUG は org.springframework.web を DEBUG に設定します。

上記のアプローチは、パッケージレベルのロギングでのみ機能します。緩いバインディングは常に環境変数を小文字に変換するため、この方法で個々のクラスのログを構成することはできません。クラスのログを構成する必要がある場合は、SPRING_APPLICATION_JSON 変数を使用できます。

4.6. ロググループ

関連するロガーをグループ化して、すべてを同時に構成できると便利なことがよくあります。例: Tomcat 関連のすべてのロガーのログレベルを一般的に変更する可能性がありますが、トップレベルのパッケージを簡単に覚えることはできません。

これを支援するために、Spring Boot では、Spring Environment でロギンググループを定義できます。例: application.properties に "tomcat" グループを追加して定義する方法は次のとおりです。

Properties
logging.group.tomcat=org.apache.catalina,org.apache.coyote,org.apache.tomcat
Yaml
logging:
  group:
    tomcat: "org.apache.catalina,org.apache.coyote,org.apache.tomcat"

定義したら、グループ内のすべてのロガーのレベルを 1 行で変更できます。

Properties
logging.level.tomcat=trace
Yaml
logging:
  level:
    tomcat: "trace"

Spring Boot には、すぐに使用できる次の事前定義されたロギンググループが含まれています。

名前 ロガー

web

org.springframework.core.codec, org.springframework.http, org.springframework.web, org.springframework.boot.actuate.endpoint.web, org.springframework.boot.web.servlet.ServletContextInitializerBeans

sql

org.springframework.jdbc.core, org.hibernate.SQL, org.jooq.tools.LoggerListener

4.7. ログシャットダウンフックの使用

アプリケーションの終了時にロギングリソースを解放するために、JVM の終了時にログシステムのクリーンアップをトリガーするシャットダウンフックが提供されています。このシャットダウンフックは、アプリケーションが war ファイルとしてデプロイされていない限り、自動的に登録されます。アプリケーションに複雑なコンテキスト階層がある場合、シャットダウンフックがニーズを満たさない可能性があります。そうでない場合は、シャットダウンフックを無効にして、基盤となるロギングシステムによって直接提供されるオプションを調べましょう。例: Logback は、各ロガーを独自のコンテキストで作成できるようにするコンテキストセレクターを提供 (英語) します。 logging.register-shutdown-hook プロパティを使用して、シャットダウンフックを無効にすることができます。false に設定すると、登録が無効になります。プロパティは、application.properties または application.yaml ファイルで設定できます。

Properties
logging.register-shutdown-hook=false
Yaml
logging:
  register-shutdown-hook: false

4.8. カスタムログ設定

さまざまなロギングシステムは、クラスパスに適切なライブラリを含めることでアクティブにでき、クラスパスのルートまたは次の Spring Environment プロパティで指定された場所に適切な構成ファイルを提供することでさらにカスタマイズできます: logging.config

org.springframework.boot.logging.LoggingSystem システムプロパティを使用して、Spring Boot に特定のログシステムを強制的に使用させることができます。値は、LoggingSystem 実装の完全修飾クラス名でなければなりません。none の値を使用して、Spring Boot のログ設定を完全に無効にすることもできます。

ApplicationContext が作成される前にロギングが初期化されるため、Spring @Configuration ファイルの @PropertySources からのロギングを制御することはできません。ロギングシステムを変更または完全に無効にする唯一の方法は、システムプロパティを使用することです。

ロギングシステムに応じて、次のファイルがロードされます。

ロギングシステム カスタム

Logback

logback-spring.xml, logback-spring.groovy, logback.xml, or logback.groovy

Log4j2

log4j2-spring.xml or log4j2.xml

JDK (Java Util Logging)

logging.properties

可能な場合、ロギング構成に -spring バリアントを使用することをお勧めします(たとえば、logback.xml ではなく logback-spring.xml)。標準の構成場所を使用する場合、Spring はログの初期化を完全に制御できません。
Java Util Logging には、「実行可能な jar」から実行するときに課題を引き起こす既知のクラスローディングの課題があります。「実行可能な jar」から実行する場合は、可能な限り回避することをお勧めします。

カスタマイズを容易にするために、他のいくつかのプロパティが Spring Environment からシステムプロパティに転送されます。これにより、システム構成のログ記録によってプロパティを使用できるようになります。例: 環境変数として application.properties または LOGGING_FILE_NAME に logging.file.name を設定すると、LOG_FILE システムプロパティが設定されます。転送されるプロパティについては、次の表で説明します。

Spring 環境 システムプロパティ コメント

logging.exception-conversion-word

LOG_EXCEPTION_CONVERSION_WORD

例外を記録するときに使用される変換語。

logging.file.name

LOG_FILE

定義されている場合、デフォルトのログ構成で使用されます。

logging.file.path

LOG_PATH

定義されている場合、デフォルトのログ構成で使用されます。

logging.pattern.console

CONSOLE_LOG_PATTERN

コンソール(stdout)で使用するログパターン。

logging.pattern.dateformat

LOG_DATEFORMAT_PATTERN

ログ日付形式のアペンダーパターン。

logging.charset.console

CONSOLE_LOG_CHARSET

コンソールログに使用する文字セット。

logging.threshold.console

CONSOLE_LOG_THRESHOLD

コンソールロギングに使用するログレベルのしきい値。

logging.pattern.file

FILE_LOG_PATTERN

ファイルで使用するログパターン(LOG_FILE が有効な場合)。

logging.charset.file

FILE_LOG_CHARSET

ファイルロギングに使用する文字セット(LOG_FILE が有効になっている場合)。

logging.threshold.file

FILE_LOG_THRESHOLD

ファイルのロギングに使用するログレベルのしきい値。

logging.pattern.level

LOG_LEVEL_PATTERN

ログレベルをレンダリングするときに使用する形式(デフォルト %5p)。

PID

PID

現在のプロセス ID(可能な場合、OS 環境変数としてまだ定義されていない場合に検出されます)。

Logback を使用する場合、次のプロパティも転送されます。

Spring 環境 システムプロパティ コメント

logging.logback.rollingpolicy.file-name-pattern

LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN

ロールオーバーされたログファイル名のパターン(デフォルト ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz)。

logging.logback.rollingpolicy.clean-history-on-start

LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START

起動時にアーカイブログファイルをクリーンアップするかどうか。

logging.logback.rollingpolicy.max-file-size

LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE

ログファイルの最大サイズ。

logging.logback.rollingpolicy.total-size-cap

LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP

保持するログバックアップの合計サイズ。

logging.logback.rollingpolicy.max-history

LOGBACK_ROLLINGPOLICY_MAX_HISTORY

保持するアーカイブログファイルの最大数。

サポートされているすべてのログシステムは、構成ファイルを解析するときにシステムプロパティを参照できます。例については、spring-boot.jar のデフォルト構成を参照してください。

ロギングプロパティでプレースホルダーを使用する場合は、基になるフレームワークの構文ではなく、Spring Boot の構文を使用する必要があります。特に、Logback を使用する場合は、: をプロパティ名とそのデフォルト値の間の区切り文字として使用し、:- は使用しないでください。

LOG_LEVEL_PATTERN (または Logback で logging.pattern.level)のみをオーバーライドすることにより、MDC およびその他のアドホックコンテンツをログ行に追加できます。例: logging.pattern.level=user:%X{user} %5p を使用する場合、デフォルトのログ形式には、次の例に示すように、"user" の MDC エントリが含まれます(存在する場合)。

2019-08-30 12:30:04.031 user:someone INFO 22174 --- [  nio-8080-exec-0] demo.Controller
Handling authenticated request

4.9. Logback 拡張

Spring Boot には、高度な構成に役立つ Logback の拡張機能が多数含まれています。これらの拡張機能を logback-spring.xml 構成ファイルで使用できます。

標準の logback.xml 構成ファイルのロードが早すぎるため、拡張機能を使用できません。logback-spring.xml を使用するか、logging.config プロパティを定義する必要があります。
拡張は Logback の構成スキャンで (英語) は使用できません。設定しようとすると、構成ファイルに変更を加えると、次のいずれかのエラーがログに記録されます。
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProperty], current ElementPath is [[configuration][springProperty]]
ERROR in ch.qos.logback.core.joran.spi.Interpreter@4:71 - no applicable action for [springProfile], current ElementPath is [[configuration][springProfile]]

4.9.1. プロファイル固有の構成

<springProfile> タグを使用すると、アクティブな Spring プロファイルに基づいて、オプションで構成のセクションを含めたり除外したりできます。プロファイルセクションは、<configuration> 要素内のどこでもサポートされます。name 属性を使用して、構成を受け入れるプロファイルを指定します。<springProfile> タグには、プロファイル名 ( staging など) またはプロファイル式を含めることができます。プロファイル式を使用すると、production & (eu-central | eu-west) など、より複雑なプロファイルロジックを表現できます。詳細については、Spring Framework リファレンスガイドを確認してください。次のリストは、3 つのサンプルプロファイルを示しています。

<springProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</springProfile>

<springProfile name="dev | staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</springProfile>

<springProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</springProfile>

4.9.2. 環境プロパティ

<springProperty> タグを使用すると、Spring から Environment のプロパティを公開して、Logback 内で使用できます。これは、Logback 構成の application.properties ファイルの値にアクセスする場合に役立ちます。このタグは、Logback の標準 <property> タグと同様に機能します。ただし、直接 value を指定するのではなく、プロパティの source を(Environment から)指定します。local スコープ以外の場所にプロパティを保存する必要がある場合は、scope 属性を使用できます。フォールバック値が必要な場合(プロパティが Environment に設定されていない場合)、defaultValue 属性を使用できます。次の例は、Logback 内で使用するプロパティを公開する方法を示しています。

<springProperty scope="context" name="fluentHost" source="myapp.fluentd.host"
        defaultValue="localhost"/>
<appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender">
    <remoteHost>${fluentHost}</remoteHost>
    ...
</appender>
source は、ケバブの場合(my.property-name など)で指定する必要があります。ただし、緩和されたルールを使用して、Environment にプロパティを追加できます。

4.10. Log4j2 拡張機能

Spring Boot には、高度な構成に役立つ Log4j2 の拡張機能が多数含まれています。これらの拡張子は、任意の log4j2-spring.xml 構成ファイルで使用できます。

標準の log4j2.xml 構成ファイルのロードが早すぎるため、拡張機能を使用できません。log4j2-spring.xml を使用するか、logging.config プロパティを定義する必要があります。
拡張機能は、Log4J によって提供される Spring Boot サポート [Apache] (英語) に取って代わります。ビルドに org.apache.logging.log4j:log4j-spring-boot モジュールを含めないようにしてください。

4.10.1. プロファイル固有の構成

<SpringProfile> タグを使用すると、アクティブな Spring プロファイルに基づいて、オプションで構成のセクションを含めたり除外したりできます。プロファイルセクションは、<Configuration> 要素内のどこでもサポートされます。name 属性を使用して、構成を受け入れるプロファイルを指定します。<SpringProfile> タグには、プロファイル名 ( staging など) またはプロファイル式を含めることができます。プロファイル式を使用すると、production & (eu-central | eu-west) など、より複雑なプロファイルロジックを表現できます。詳細については、Spring Framework リファレンスガイドを確認してください。次のリストは、3 つのサンプルプロファイルを示しています。

<SpringProfile name="staging">
    <!-- configuration to be enabled when the "staging" profile is active -->
</SpringProfile>

<SpringProfile name="dev | staging">
    <!-- configuration to be enabled when the "dev" or "staging" profiles are active -->
</SpringProfile>

<SpringProfile name="!production">
    <!-- configuration to be enabled when the "production" profile is not active -->
</SpringProfile>

4.10.2. 環境プロパティのルックアップ

Log4j2 構成内で Spring Environment からプロパティを参照する場合は、spring: プレフィックス付きルックアップ [Apache] (英語) を使用できます。これは、Log4j2 構成の application.properties ファイルから値にアクセスする場合に役立ちます。

次の例は、Spring Environment から spring.application.name を読み取る applicationName という名前の Log4j2 プロパティを設定する方法を示しています。

<Properties>
    <Property name="applicationName">${spring:spring.application.name}</Property>
</Properties>
ルックアップキーはケバブケース ( my.property-name など) で指定する必要があります。

4.10.3. Log4j2 システムプロパティ

Log4j2 は、さまざまな項目の構成に使用できる多数のシステムプロパティ [Apache] (英語) をサポートしています。例: log4j2.skipJansi システムプロパティを使用して、ConsoleAppender が Windows でジャンシ [GitHub] (英語) 出力ストリームを使用しようとするかどうかを構成できます。

Log4j2 の初期化後に読み込まれるすべてのシステムプロパティは、Spring Environment から取得できます。例: log4j2.skipJansi=false を application.properties ファイルに追加して、ConsoleAppender が Windows で Jansi を使用するようにすることができます。

Spring Environment は、システムプロパティと OS 環境変数にロードされる値が含まれていない場合にのみ考慮されます。
初期の Log4j2 初期化中にロードされるシステムプロパティは、Spring Environment を参照できません。例: デフォルトの Log4j2 実装を選択できるようにするために Log4j2 が使用するプロパティは、Spring 環境が使用可能になる前に使用されます。

5. 国際化対応

Spring Boot はローカライズされたメッセージをサポートしているため、アプリケーションは異なる言語設定のユーザーに対応できます。デフォルトでは、Spring Boot は、クラスパスのルートで messages リソースバンドルの存在を探します。

自動構成は、構成されたリソースバンドルのデフォルトのプロパティファイルが使用可能な場合に適用されます(デフォルトでは messages.properties)。リソースバンドルに言語固有のプロパティファイルのみが含まれている場合は、デフォルトを追加する必要があります。構成されたベース名のいずれかに一致するプロパティファイルが見つからない場合、自動構成された MessageSource はありません。

次の例に示すように、spring.messages 名前空間を使用して、リソースバンドルのベース名と他のいくつかの属性を構成できます。

Properties
spring.messages.basename=messages,config.i18n.messages
spring.messages.fallback-to-system-locale=false
Yaml
spring:
  messages:
    basename: "messages,config.i18n.messages"
    fallback-to-system-locale: false
spring.messages.basename は、パッケージ修飾子またはクラスパスルートから解決されたリソースのいずれかの場所のコンマ区切りリストをサポートします。

サポートされるオプションの詳細については、MessageSourceProperties [GitHub] (英語) を参照してください。

6. アスペクト指向プログラミング

Spring Boot は、アスペクト指向プログラミング (AOP) の自動構成を提供します。AOP の詳細については、Spring Framework リファレンスドキュメントの Spring を参照してください。

デフォルトでは、Spring Boot の自動構成により、CGLib プロキシを使用するように Spring AOP が構成されます。代わりに JDK プロキシを使用するには、spring.aop.proxy-target-class を false に設定します。

AspectJ がクラスパス上にある場合、Spring Boot の自動構成により AspectJ 自動プロキシが自動的に有効になり、@EnableAspectJAutoProxy は必要なくなります。

7. JSON

Spring Boot は、3 つの JSON マッピングライブラリとの統合を提供します。

  • Gson

  • Jackson

  • JSON-B

Jackson は、推奨されるデフォルトのライブラリです。

7.1. Jackson

Jackson の自動構成が提供され、Jackson は spring-boot-starter-json の一部です。Jackson がクラスパスにある場合、ObjectMapper Bean が自動的に構成されます。ObjectMapper の構成をカスタマイズするために、いくつかの構成プロパティが提供されています

7.1.1. カスタムシリアライザーとデシリアライザー

Jackson を使用して JSON データをシリアライズおよびデシリアライズする場合、独自の JsonSerializer および JsonDeserializer クラスを作成することができます。カスタムシリアライザーは通常、モジュールを介して Jackson に登録されます [GitHub] (英語) が、Spring Boot は Spring Bean を直接登録しやすくする代替 @JsonComponent アノテーションを提供します。

JsonSerializerJsonDeserializer または KeyDeserializer 実装で @JsonComponent アノテーションを直接使用できます。次の例に示すように、内部クラスとしてシリアライザー / デシリアライザーを含むクラスでも使用できます。

Java
import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import org.springframework.boot.jackson.JsonComponent;

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonSerializer<MyObject> {

        @Override
        public void serialize(MyObject value, JsonGenerator jgen, SerializerProvider serializers) throws IOException {
            jgen.writeStartObject();
            jgen.writeStringField("name", value.getName());
            jgen.writeNumberField("age", value.getAge());
            jgen.writeEndObject();
        }

    }

    public static class Deserializer extends JsonDeserializer<MyObject> {

        @Override
        public MyObject deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
            ObjectCodec codec = jsonParser.getCodec();
            JsonNode tree = codec.readTree(jsonParser);
            String name = tree.get("name").textValue();
            int age = tree.get("age").intValue();
            return new MyObject(name, age);
        }

    }

}
Kotlin
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.SerializerProvider
import org.springframework.boot.jackson.JsonComponent
import java.io.IOException

@JsonComponent
class MyJsonComponent {

    class Serializer : JsonSerializer<MyObject>() {
        @Throws(IOException::class)
        override fun serialize(value: MyObject, jgen: JsonGenerator, serializers: SerializerProvider) {
            jgen.writeStartObject()
            jgen.writeStringField("name", value.name)
            jgen.writeNumberField("age", value.age)
            jgen.writeEndObject()
        }
    }

    class Deserializer : JsonDeserializer<MyObject>() {
        @Throws(IOException::class, JsonProcessingException::class)
        override fun deserialize(jsonParser: JsonParser, ctxt: DeserializationContext): MyObject {
            val codec = jsonParser.codec
            val tree = codec.readTree<JsonNode>(jsonParser)
            val name = tree["name"].textValue()
            val age = tree["age"].intValue()
            return MyObject(name, age)
        }
    }

}

ApplicationContext 内のすべての @JsonComponent Bean は、Jackson に自動的に登録されます。@JsonComponent は @Component でメタアノテーションが付けられているため、通常のコンポーネントスキャンルールが適用されます。

Spring Boot は、オブジェクトを直列化するときに標準 Jackson バージョンの有用な代替を提供する JsonObjectSerializer [GitHub] (英語) および JsonObjectDeserializer [GitHub] (英語) 基本クラスも提供します。詳細については、Javadoc の JsonObjectSerializer (Javadoc) および JsonObjectDeserializer (Javadoc) を参照してください。

上記の例は、JsonObjectSerializer/JsonObjectDeserializer を使用するように次のように書き直すことができます。

Java
import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.SerializerProvider;

import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.jackson.JsonObjectDeserializer;
import org.springframework.boot.jackson.JsonObjectSerializer;

@JsonComponent
public class MyJsonComponent {

    public static class Serializer extends JsonObjectSerializer<MyObject> {

        @Override
        protected void serializeObject(MyObject value, JsonGenerator jgen, SerializerProvider provider)
                throws IOException {
            jgen.writeStringField("name", value.getName());
            jgen.writeNumberField("age", value.getAge());
        }

    }

    public static class Deserializer extends JsonObjectDeserializer<MyObject> {

        @Override
        protected MyObject deserializeObject(JsonParser jsonParser, DeserializationContext context, ObjectCodec codec,
                JsonNode tree) throws IOException {
            String name = nullSafeValue(tree.get("name"), String.class);
            int age = nullSafeValue(tree.get("age"), Integer.class);
            return new MyObject(name, age);
        }

    }

}
Kotlin
`object`

import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.ObjectCodec
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.SerializerProvider
import org.springframework.boot.jackson.JsonComponent
import org.springframework.boot.jackson.JsonObjectDeserializer
import org.springframework.boot.jackson.JsonObjectSerializer
import java.io.IOException

@JsonComponent
class MyJsonComponent {

    class Serializer : JsonObjectSerializer<MyObject>() {
        @Throws(IOException::class)
        override fun serializeObject(value: MyObject, jgen: JsonGenerator, provider: SerializerProvider) {
            jgen.writeStringField("name", value.name)
            jgen.writeNumberField("age", value.age)
        }
    }

    class Deserializer : JsonObjectDeserializer<MyObject>() {
        @Throws(IOException::class)
        override fun deserializeObject(jsonParser: JsonParser, context: DeserializationContext,
                codec: ObjectCodec, tree: JsonNode): MyObject {
            val name = nullSafeValue(tree["name"], String::class.java)
            val age = nullSafeValue(tree["age"], Int::class.java)
            return MyObject(name, age)
        }
    }

}

7.1.2. Mixins

Jackson は、ターゲットクラスですでに宣言されているアノテーションに追加のアノテーションをミックスするために使用できるミックスインをサポートしています。Spring Boot の Jackson 自動構成は、アプリケーションのパッケージをスキャンして @JsonMixin でアノテーションが付けられたクラスを探し、自動構成された ObjectMapper に登録します。登録は Spring Boot の JsonMixinModule によって実行されます。

7.2. Gson

Gson の自動構成が提供されます。Gson がクラスパスにある場合、Gson Bean が自動的に構成されます。構成をカスタマイズするために、いくつかの spring.gson.* 構成プロパティが提供されています。さらに制御するには、1 つ以上の GsonBuilderCustomizer Bean を使用できます。

7.3. JSON-B

JSON-B の自動構成が提供されます。JSON-B API と実装がクラスパス上にある場合、Jsonb Bean が自動的に構成されます。推奨される JSON-B 実装は、依存関係管理が提供されている Eclipse Yasson です。

8. タスクの実行とスケジューリング

コンテキスト内に Executor Bean が存在しない場合、Spring Boot は AsyncTaskExecutor を自動構成します。仮想スレッドが有効になっている場合 ( Java 21+ および spring.threads.virtual.enabled を true に設定して使用)、これは仮想スレッドを使用する SimpleAsyncTaskExecutor になります。それ以外の場合は、適切なデフォルトの ThreadPoolTaskExecutor になります。どちらの場合も、自動構成されたエグゼキュータは次の目的で自動的に使用されます。

  • 非同期タスクの実行 (@EnableAsync)

  • Spring for GraphQL によるコントローラーメソッドからの Callable 戻り値の非同期処理

  • Spring MVC の非同期リクエスト処理

  • Spring WebFlux のブロッキング実行サポート

コンテキスト内でカスタム Executor を定義した場合、通常のタスク実行 (つまり @EnableAsync) と Spring for GraphQL の両方でそれが使用されます。ただし、Spring MVC および Spring WebFlux サポートは、それが AsyncTaskExecutor 実装 ( applicationTaskExecutor という名前) である場合にのみ使用します。ターゲットの配置に応じて、Executor を AsyncTaskExecutor に変更することも、カスタム Executor をラップする AsyncTaskExecutor と AsyncConfigurer の両方を定義することもできます。

自動構成された ThreadPoolTaskExecutorBuilder を使用すると、自動構成がデフォルトで行うことを再現するインスタンスを簡単に作成できます。

ThreadPoolTaskExecutor が自動構成されている場合、スレッドプールは負荷に応じて拡大または縮小できる 8 コアスレッドを使用します。これらのデフォルト設定は、次の例に示すように、spring.task.execution 名前空間を使用して微調整できます。

Properties
spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s
Yaml
spring:
  task:
    execution:
      pool:
        max-size: 16
        queue-capacity: 100
        keep-alive: "10s"

これにより、キューがいっぱい(100 タスク)になったときにスレッドプールが最大 16 スレッドに増加するように、スレッドプールが制限キューを使用するように変更されます。プールの縮小は、スレッドが 10 秒間(デフォルトでは 60 秒ではなく)アイドル状態のときに回収されるため、より積極的です。

スケジュールされたタスクの実行に関連付ける必要がある場合は、スケジューラを自動構成することもできます (たとえば、@EnableScheduling を使用)。

仮想スレッドが有効になっている場合 ( Java 21+ および spring.threads.virtual.enabled を true に設定して使用)、これは仮想スレッドを使用する SimpleAsyncTaskScheduler になります。この SimpleAsyncTaskScheduler は、プーリング関連のプロパティを無視します。

仮想スレッドが有効になっていない場合は、適切なデフォルトの ThreadPoolTaskScheduler になります。ThreadPoolTaskScheduler はデフォルトで 1 つのスレッドを使用し、次の例に示すように、その設定は spring.task.scheduling 名前空間を使用して微調整できます。

Properties
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
Yaml
spring:
  task:
    scheduling:
      thread-name-prefix: "scheduling-"
      pool:
        size: 2

カスタムエグゼキュータまたはスケジューラを作成する必要がある場合は、ThreadPoolTaskExecutorBuilder Bean、SimpleAsyncTaskExecutorBuilder Bean、ThreadPoolTaskSchedulerBuilder Bean、SimpleAsyncTaskSchedulerBuilder がコンテキストで使用可能になります。SimpleAsyncTaskExecutorBuilder Bean および SimpleAsyncTaskSchedulerBuilder Bean は、有効になっている場合 ( true に設定された Java 21+ および spring.threads.virtual.enabled を使用)、仮想スレッドを使用するように自動構成されます。

9. テスト

Spring Boot は、アプリケーションをテストするときに役立つ多くのユーティリティとアノテーションを提供します。テストサポートは 2 つのモジュールによって提供されます。spring-boot-test にはコアアイテムが含まれ、spring-boot-test-autoconfigure はテストの自動構成をサポートします。

ほとんどの開発者は、Spring Boot テストモジュールと JUnit Jupiter、AssertJ、Hamcrest、その他の便利なライブラリの両方をインポートする spring-boot-starter-test “Starter”を使用します。

JUnit 4 を使用するテストがある場合、JUnit 5 の Vintage エンジンを使用してテストを実行できます。ヴィンテージエンジンを使用するには、次の例に示すように、junit-vintage-engine への依存関係を追加します。

<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

hamcrest-core は除外され、spring-boot-starter-test の一部である org.hamcrest:hamcrest が優先されます。

9.1. テスト範囲の依存関係

spring-boot-starter-test 「スターター」(test scope 内)には、以下の提供されたライブラリが含まれています。

通常、これらの一般的なライブラリは、テストを作成するときに役立つことがわかります。これらのライブラリがニーズに合わない場合は、独自のテスト依存関係を追加できます。

9.2. Spring アプリケーションのテスト

依存性注入の主な利点の 1 つは、コードを単体テストしやすくすることです。Spring を使用しなくても、new 演算子を使用してオブジェクトをインスタンス化できます。実際の依存関係の代わりにモックオブジェクトを使用することもできます

多くの場合、単体テストを超えて統合テストを開始する必要があります(Spring ApplicationContext を使用)。アプリケーションのデプロイを必要とせずに、または他のインフラストラクチャに接続する必要なく、統合テストを実行できると便利です。

Spring Framework には、このような統合テスト専用のテストモジュールが含まれています。org.springframework:spring-test に直接依存関係を宣言するか、spring-boot-starter-test 「スターター」を使用して依存関係を一時的にプルできます。

spring-test モジュールを使用したことがない場合は、Spring Framework リファレンスドキュメントの関連セクションを読むことから始めてください。

9.3. Spring Boot アプリケーションのテスト

Spring Boot アプリケーションは Spring ApplicationContext であるため、バニラ Spring コンテキストで通常行うことを超えてテストするために特別なことは何もする必要はありません。

Spring Boot の外部プロパティ、ロギング、その他の機能は、SpringApplication を使用して作成する場合にのみ、デフォルトでコンテキストにインストールされます。

Spring Boot は @SpringBootTest アノテーションを提供します。これは、Spring Boot 機能が必要な場合に、標準の spring-test @ContextConfiguration アノテーションの代わりに使用できます。アノテーションは、SpringApplication を介してテストで使用される ApplicationContext を作成することによって機能します@SpringBootTest に加えて、アプリケーションのより具体的なスライステストするために、他の多くのアノテーションも提供されています。

JUnit 4 を使用している場合は、@RunWith(SpringRunner.class) もテストに追加することを忘れないでください。そうしないと、アノテーションが無視されます。JUnit 5 を使用している場合は、同等の @ExtendWith(SpringExtension.class) を @SpringBootTest として追加する必要はなく、他の @…​Test アノテーションにはすでにアノテーションが付けられています。

デフォルトでは、@SpringBootTest はサーバーを起動しません。@SpringBootTest の webEnvironment 属性を使用して、テストの実行方法をさらに絞り込むことができます。

  • MOCK(デフォルト): Web ApplicationContext をロードし、モック Web 環境を提供します。このアノテーションを使用すると、組み込みサーバーは起動しません。Web 環境がクラスパスで利用できない場合、このモードは通常の非 Web ApplicationContext の作成に透過的にフォールバックします。Web アプリケーションのモックベースのテストのために、@AutoConfigureMockMvc または @AutoConfigureWebTestClient と組み合わせて使用できます。

  • RANDOM_PORTWebServerApplicationContext をロードし、実際の Web 環境を提供します。組み込みサーバーが起動され、ランダムポートでリッスンします。

  • DEFINED_PORTWebServerApplicationContext をロードし、実際の Web 環境を提供します。組み込みサーバーが開始され、定義済みのポート(application.properties から)またはデフォルトのポート 8080 で listen します。

  • NONESpringApplication を使用して ApplicationContext をロードしますが Web 環境(モックまたはその他)を提供しません。

テストが @Transactional の場合、デフォルトで各テストメソッドの最後にトランザクションをロールバックします。ただし、RANDOM_PORT または DEFINED_PORT のいずれかでこの配置を使用すると、実際のサーブレット環境が暗黙的に提供されるため、HTTP クライアントとサーバーは別々のスレッドで、別々のトランザクションで実行されます。この場合、サーバーで開始されたトランザクションはロールバックしません。
@SpringBootTest と webEnvironment = WebEnvironment.RANDOM_PORT は、アプリケーションが管理サーバーに異なるポートを使用している場合、別のランダムポートで管理サーバーを起動します。

9.3.1. Web アプリケーション型の検出

Spring MVC が使用可能な場合、通常の MVC ベースのアプリケーションコンテキストが構成されます。Spring WebFlux しかない場合は、それを検出し、代わりに WebFlux ベースのアプリケーションコンテキストを構成します。

両方が存在する場合、Spring MVC が優先されます。このシナリオでリアクティブ Web アプリケーションをテストする場合は、spring.main.web-application-type プロパティを設定する必要があります。

Java
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest(properties = "spring.main.web-application-type=reactive")
class MyWebFluxTests {

    // ...

}
Kotlin
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest(properties = ["spring.main.web-application-type=reactive"])
class MyWebFluxTests {

    // ...

}

9.3.2. テスト構成の検出

Spring Test フレームワークに精通している場合は、ロードする Spring @Configuration を指定するために @ContextConfiguration(classes=…​) を使用することに慣れているかもしれません。または、テスト内でネストされた @Configuration クラスを頻繁に使用した可能性があります。

Spring Boot アプリケーションをテストする場合、これは多くの場合必要ありません。Spring Boot の @*Test アノテーションは、明示的に定義しない限り、プライマリ設定を自動的に検索します。

検索アルゴリズムは、@SpringBootApplication または @SpringBootConfiguration アノテーションが付けられたクラスを見つけるまで、テストを含むパッケージから機能します。実用的なメソッドでコードを構造化する限り、通常、メイン構成が見つかります。

@SpringBootApplication の基礎となるコンポーネントスキャン構成は、スライスが期待どおりに機能することを確認するために使用される除外フィルターを定義します。@SpringBootApplication アノテーション付きクラスで明示的な @ComponentScan ディレクティブを使用している場合は、これらのフィルターが無効になることに注意してください。スライスを使用している場合は、再度定義する必要があります。

プライマリ設定をカスタマイズする場合は、ネストされた @TestConfiguration クラスを使用できます。アプリケーションのプライマリ設定の代わりに使用されるネストされた @Configuration クラスとは異なり、ネストされた @TestConfiguration クラスはアプリケーションのプライマリ設定に加えて使用されます。

Spring のテストフレームワークは、テスト間のアプリケーションコンテキストをキャッシュします。テストが同じ構成を共有している限り(検出方法に関係なく)、コンテキストをロードする潜在的に時間のかかるプロセスは 1 回しか発生しません。

9.3.3. テストコンフィギュレーションのメインメソッドの使用

通常、@SpringBootTest によって検出されたテスト構成は、メインの @SpringBootApplication になります。ほとんどの適切に構造化されたアプリケーションでは、この構成クラスには、アプリケーションの起動に使用される main メソッドも含まれます。

例: 以下は、典型的な Spring Boot アプリケーションの非常に一般的なコードパターンです。

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.docs.using.structuringyourcode.locatingthemainclass.MyApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class MyApplication

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

上記の例では、main メソッドは SpringApplication.run への委譲以外は何もしません。ただし、SpringApplication.run を呼び出す前にカスタマイズを適用する、より複雑な main メソッドを持つことは可能です。

例: バナーモードを変更し、追加のプロファイルを設定するアプリケーションは次のとおりです。

Java
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.setAdditionalProfiles("myprofile");
        application.run(args);
    }

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

@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
    runApplication<MyApplication>(*args) {
        setBannerMode(Banner.Mode.OFF)
        setAdditionalProfiles("myprofile")
    }
}

main メソッドのカスタマイズは、結果の ApplicationContext に影響を与える可能性があるため、main メソッドを使用して、テストで使用される ApplicationContext を作成することもできます。デフォルトでは、@SpringBootTest は main メソッドを呼び出さず、代わりにクラス自体を直接使用して ApplicationContext を作成します。

この動作を変更する場合は、@SpringBootTest の useMainMethod 属性を UseMainMethod.ALWAYS または UseMainMethod.WHEN_AVAILABLE に変更できます。ALWAYS に設定すると、main メソッドが見つからない場合、テストは失敗します。WHEN_AVAILABLE に設定すると、main メソッドが使用可能であればそれが使用されます。それ以外の場合は、標準の読み込みメカニズムが使用されます。

例: 次のテストは、ApplicationContext を作成するために MyApplication の main メソッドを呼び出します。メインメソッドが追加のプロファイルを設定すると、ApplicationContext の開始時にそれらがアクティブになります。

Java
import org.junit.jupiter.api.Test;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.UseMainMethod;

@SpringBootTest(useMainMethod = UseMainMethod.ALWAYS)
class MyApplicationTests {

    @Test
    void exampleTest() {
        // ...
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.UseMainMethod

@SpringBootTest(useMainMethod = UseMainMethod.ALWAYS)
class MyApplicationTests {

    @Test
    fun exampleTest() {
        // ...
    }

}

9.3.4. テスト構成の除外

アプリケーションがコンポーネントスキャンを使用している場合(たとえば、@SpringBootApplication または @ComponentScan を使用している場合)、特定のテスト用に作成した最上位の構成クラスが誤ってどこでも取得される可能性があります。

前に見たように、@TestConfiguration をテストの内部クラスで使用して、主要な構成をカスタマイズできます。@TestConfiguration は最上位クラスでも使用可能です。これは、そのクラスがスキャンによって検出されるべきではないことを示します。次に、次の例に示すように、必要な場所にクラスを明示的にインポートできます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;

@SpringBootTest
@Import(MyTestsConfiguration.class)
class MyTests {

    @Test
    void exampleTest() {
        // ...
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.context.annotation.Import

@SpringBootTest
@Import(MyTestsConfiguration::class)
class MyTests {

    @Test
    fun exampleTest() {
        // ...
    }

}
@ComponentScan を直接使用する場合(つまり、@SpringBootApplication を使用しない場合)、TypeExcludeFilter を登録する必要があります。詳細については、Javadoc を参照してください。
インポートされた @TestConfiguration は内部クラスの @TestConfiguration よりも先に処理され、インポートされた @TestConfiguration はコンポーネントのスキャンで検出された構成よりも前に処理されます。一般に、この順序の違いは目立った影響はありませんが、Bean のオーバーライドに依存している場合は注意が必要です。

9.3.5. アプリケーション引数の使用

アプリケーションで引数が必要な場合は、args 属性を使用して @SpringBootTest に引数を注入させることができます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.test.context.SpringBootTest;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(args = "--app.test=one")
class MyApplicationArgumentTests {

    @Test
    void applicationArgumentsPopulated(@Autowired ApplicationArguments args) {
        assertThat(args.getOptionNames()).containsOnly("app.test");
        assertThat(args.getOptionValues("app.test")).containsOnly("one");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.ApplicationArguments
import org.springframework.boot.test.context.SpringBootTest

@SpringBootTest(args = ["--app.test=one"])
class MyApplicationArgumentTests {

    @Test
    fun applicationArgumentsPopulated(@Autowired args: ApplicationArguments) {
        assertThat(args.optionNames).containsOnly("app.test")
        assertThat(args.getOptionValues("app.test")).containsOnly("one")
    }

}

9.3.6. モック環境でのテスト

デフォルトでは、@SpringBootTest はサーバーを起動しませんが、代わりに Web エンドポイントをテストするためのモック環境をセットアップします。

次の例に示すように、Spring MVC を使用すると、MockMvc または WebTestClient を使用して Web エンドポイントにクエリを実行できます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class MyMockMvcTests {

    @Test
    void testWithMockMvc(@Autowired MockMvc mvc) throws Exception {
        mvc.perform(get("/")).andExpect(status().isOk()).andExpect(content().string("Hello World"));
    }

    // If Spring WebFlux is on the classpath, you can drive MVC tests with a WebTestClient
    @Test
    void testWithWebTestClient(@Autowired WebTestClient webClient) {
        webClient
                .get().uri("/")
                .exchange()
                .expectStatus().isOk()
                .expectBody(String.class).isEqualTo("Hello World");
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers

@SpringBootTest
@AutoConfigureMockMvc
class MyMockMvcTests {

    @Test
    fun testWithMockMvc(@Autowired mvc: MockMvc) {
        mvc.perform(MockMvcRequestBuilders.get("/")).andExpect(MockMvcResultMatchers.status().isOk)
            .andExpect(MockMvcResultMatchers.content().string("Hello World"))
    }

    // If Spring WebFlux is on the classpath, you can drive MVC tests with a WebTestClient

    @Test
    fun testWithWebTestClient(@Autowired webClient: WebTestClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk
            .expectBody<String>().isEqualTo("Hello World")
    }

}
完全な ApplicationContext を開始せずに Web レイヤーのみに焦点を合わせたい場合は、代わりに @WebMvcTest の使用を検討してください

Spring WebFlux エンドポイントでは、次の例に示すように WebTestClient を使用できます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.reactive.server.WebTestClient;

@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {

    @Test
    void exampleTest(@Autowired WebTestClient webClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk()
            .expectBody(String.class).isEqualTo("Hello World");
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody

@SpringBootTest
@AutoConfigureWebTestClient
class MyMockWebTestClientTests {

    @Test
    fun exampleTest(@Autowired webClient: WebTestClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk
            .expectBody<String>().isEqualTo("Hello World")
    }

}

モック環境内でのテストは、通常、完全なサーブレットコンテナーで実行するよりも高速です。ただし、モックは Spring MVC レイヤーで発生するため、下位レベルのサーブレットコンテナーの動作に依存するコードを MockMvc で直接テストすることはできません。

例: Spring Boot のエラー処理は、サーブレットコンテナーによって提供される「エラーページ」サポートに基づいています。つまり、MVC レイヤーのスローをテストして例外を期待どおりに処理することはできますが、特定のカスタムエラーページがレンダリングされることを直接テストすることはできません。これらの下位レベルの関心事をテストする必要がある場合は、次のセクションで説明するように、完全に実行されているサーバーを起動できます。

9.3.7. 実行中のサーバーでのテスト

完全に稼働しているサーバーを起動する必要がある場合は、ランダムなポートを使用することをお勧めします。@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT) を使用すると、テストを実行するたびに使用可能なポートがランダムに選択されます。

@LocalServerPort アノテーションを使用して、テストに実際に使用されるポートを挿入できます。便宜上、開始されたサーバーに対して REST 呼び出しを行う必要があるテストでは、@Autowire に WebTestClient を追加できます。これは、実行中のサーバーへの相対リンクを解決し、次の例に示すように、レスポンスを検証する専用 API を備えています:

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.web.reactive.server.WebTestClient;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortWebTestClientTests {

    @Test
    void exampleTest(@Autowired WebTestClient webClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk()
            .expectBody(String.class).isEqualTo("Hello World");
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortWebTestClientTests {

    @Test
    fun exampleTest(@Autowired webClient: WebTestClient) {
        webClient
            .get().uri("/")
            .exchange()
            .expectStatus().isOk
            .expectBody<String>().isEqualTo("Hello World")
    }

}
WebTestClient は、テストクラスに @AutoConfigureWebTestClient アノテーションを付けることで、モック環境でも使用でき、サーバーを実行する必要がなくなります。

この設定では、クラスパスに spring-webflux が必要です。webflux を追加できない、または追加しない場合、Spring Boot は TestRestTemplate 機能も提供します。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortTestRestTemplateTests {

    @Test
    void exampleTest(@Autowired TestRestTemplate restTemplate) {
        String body = restTemplate.getForObject("/", String.class);
        assertThat(body).isEqualTo("Hello World");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.boot.test.web.client.TestRestTemplate

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyRandomPortTestRestTemplateTests {

    @Test
    fun exampleTest(@Autowired restTemplate: TestRestTemplate) {
        val body = restTemplate.getForObject("/", String::class.java)
        assertThat(body).isEqualTo("Hello World")
    }

}

9.3.8. WebTestClient のカスタマイズ

WebTestClient Bean をカスタマイズするには、WebTestClientBuilderCustomizer Bean を構成します。このような Bean は、WebTestClient の作成に使用される WebTestClient.Builder で呼び出されます。

9.3.9. JMX を使用する

テストコンテキストフレームワークはコンテキストをキャッシュするため、JMX はデフォルトで無効になり、同一ドメインに同一のコンポーネントが登録されないようにします。そのようなテストが MBeanServer にアクセスする必要がある場合、同様にダーティマークを付けることを検討してください。

Java
import javax.management.MBeanServer;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(properties = "spring.jmx.enabled=true")
@DirtiesContext
class MyJmxTests {

    @Autowired
    private MBeanServer mBeanServer;

    @Test
    void exampleTest() {
        assertThat(this.mBeanServer.getDomains()).contains("java.lang");
        // ...
    }

}
Kotlin
import javax.management.MBeanServer

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.annotation.DirtiesContext

@SpringBootTest(properties = ["spring.jmx.enabled=true"])
@DirtiesContext
class MyJmxTests(@Autowired val mBeanServer: MBeanServer) {

    @Test
    fun exampleTest() {
        assertThat(mBeanServer.domains).contains("java.lang")
        // ...
    }

}

9.3.10. 観測値の使用

スライスされたテストに @AutoConfigureObservability のアノテーションを付けると、ObservationRegistry が自動構成されます。

9.3.11. メトリクスの使用

クラスパスに関係なく、@SpringBootTest を使用する場合、メモリ内でバックアップされているものを除いて、メーターレジストリは自動構成されません。

統合テストの一環としてメトリクスを別のバックエンドにエクスポートする必要がある場合は、@AutoConfigureObservability でアノテーションを付けます。

スライスされたテストに @AutoConfigureObservability のアノテーションを付けると、メモリ内 MeterRegistry が自動構成されます。スライステストでのデータのエクスポートは、@AutoConfigureObservability アノテーションではサポートされていません。

9.3.12. トレースの使用

クラスパスに関係なく、@SpringBootTest を使用する場合、データをレポートするトレースコンポーネントは自動構成されません。

統合テストの一部としてこれらのコンポーネントが必要な場合は、テストに @AutoConfigureObservability のアノテーションを付けます。

独自のレポートコンポーネント (カスタム SpanExporter または SpanHandler など) を作成しており、テストでアクティブにしたくない場合は、@ConditionalOnEnabledTracing アノテーションを使用して無効にすることができます。

スライスされたテストに @AutoConfigureObservability のアノテーションを付けると、no-op Tracer が自動構成されます。スライステストでのデータのエクスポートは、@AutoConfigureObservability アノテーションではサポートされていません。

9.3.13. Bean のモックとスパイ

テストを実行するとき、アプリケーションコンテキスト内の特定のコンポーネントをモックする必要がある場合があります。例: 開発中は利用できないリモートサービスのファサードがある場合があります。モックは、実際の環境では引き起こしにくい障害をシミュレートする場合にも役立ちます。

Spring Boot には、ApplicationContext 内の Bean の Mockito モックを定義するために使用できる @MockBean アノテーションが含まれています。アノテーションを使用して、新しい Bean を追加したり、単一の既存の Bean 定義を置き換えることができます。アノテーションは、テストクラス、テスト内のフィールド、@Configuration クラスとフィールドで直接使用できます。フィールドで使用すると、作成されたモックのインスタンスも注入されます。モック Bean は、各テストメソッドの後に自動的にリセットされます。

テストで Spring Boot のテストアノテーションの 1 つ(@SpringBootTest など)を使用する場合、この機能は自動的に有効になります。この機能を別の配置で使用するには、次の例に示すように、リスナーを明示的に追加する必要があります。

Java
import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener;
import org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;

@ContextConfiguration(classes = MyConfig.class)
@TestExecutionListeners({ MockitoTestExecutionListener.class, ResetMocksTestExecutionListener.class })
class MyTests {

    // ...

}
Kotlin
import org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener
import org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.TestExecutionListeners

@ContextConfiguration(classes = [MyConfig::class])
@TestExecutionListeners(
    MockitoTestExecutionListener::class,
    ResetMocksTestExecutionListener::class
)
class MyTests {

    // ...

}

次の例では、既存の RemoteService Bean をモック実装に置き換えます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;

@SpringBootTest
class MyTests {

    @Autowired
    private Reverser reverser;

    @MockBean
    private RemoteService remoteService;

    @Test
    void exampleTest() {
        given(this.remoteService.getValue()).willReturn("spring");
        String reverse = this.reverser.getReverseValue(); // Calls injected RemoteService
        assertThat(reverse).isEqualTo("gnirps");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.mock.mockito.MockBean

@SpringBootTest
class MyTests(@Autowired val reverser: Reverser, @MockBean val remoteService: RemoteService) {

    @Test
    fun exampleTest() {
        given(remoteService.value).willReturn("spring")
        val reverse = reverser.reverseValue // Calls injected RemoteService
        assertThat(reverse).isEqualTo("gnirps")
    }

}
@MockBean を使用して、アプリケーションコンテキストのリフレッシュ中に実行される Bean の動作を模倣することはできません。テストが実行されるまでに、アプリケーションコンテキストのリフレッシュが完了し、モック動作を構成するには遅すぎます。この状況では、@Bean メソッドを使用してモックを作成および構成することをお勧めします。

さらに、@SpyBean を使用して、既存の Bean を Mockito spy でラップすることができます。詳細については、Javadoc を参照してください。

Spring のテストフレームワークはテスト間でアプリケーションコンテキストをキャッシュし、同じ構成を共有するテストでコンテキストを再利用しますが、@MockBean または @SpyBean の使用はキャッシュキーに影響し、コンテキストの数を増やす可能性が高くなります。
@SpyBean を使用して、名前でパラメーターを参照する @Cacheable メソッドで Bean をスパイする場合、アプリケーションは -parameters でコンパイルする必要があります。これにより、Bean がスパイされると、パラメーター名がキャッシュインフラストラクチャで使用可能になります。
@SpyBean を使用して、Spring によってプロキシされている Bean をスパイしている場合、given または when を使用して期待値を設定する場合など、状況によっては Spring のプロキシを削除する必要がある場合があります。これを行うには、AopTestUtils.getTargetObject(yourProxiedSpy) を使用します。

9.3.14. 自動構成されたテスト

Spring Boot の自動構成システムは、アプリケーションではうまく機能しますが、テストには少し多すぎる場合があります。多くの場合、アプリケーションの「スライス」をテストするために必要な構成部分のみをロードすると役立ちます。例: Spring MVC コントローラーが URL を正しくマッピングしていることをテストしたい場合があり、それらのテストにデータベース呼び出しを含めたくない場合、または JPA エンティティをテストしたい場合、それらのテストの実行時に Web レイヤーに関心がない場合 .

spring-boot-test-autoconfigure モジュールには、このような「スライス」を自動的に構成するために使用できる多くのアノテーションが含まれています。それぞれが同様に機能し、ApplicationContext をロードする @…​Test アノテーションと、自動構成設定のカスタマイズに使用できる 1 つ以上の @AutoConfigure…​ アノテーションを提供します。

各スライスは、コンポーネントスキャンを適切なコンポーネントに制限し、非常に制限された自動構成クラスのセットをロードします。それらのいずれかを除外する必要がある場合、ほとんどの @…​Test アノテーションは excludeAutoConfiguration 属性を提供します。または、@ImportAutoConfiguration#exclude を使用できます。
1 つのテストで複数の @…​Test アノテーションを使用して複数の「スライス」を含めることはサポートされていません。複数の「スライス」が必要な場合は、@…​Test アノテーションの 1 つを選択し、他の「スライス」の @AutoConfigure…​ アノテーションを手動で含めます。
@AutoConfigure…​ アノテーションを標準の @SpringBootTest アノテーションとともに使用することもできます。アプリケーションの「スライス」に興味はないが、自動構成されたテスト Bean の一部が必要な場合は、この組み合わせを使用できます。

9.3.15. 自動構成された JSON テスト

オブジェクトの JSON 直列化と逆直列化が期待どおりに機能することをテストするには、@JsonTest アノテーションを使用できます。@JsonTest は、使用可能なサポートされている JSON マッパーを自動構成します。これは、次のライブラリのいずれかです。

  • Jackson ObjectMapper@JsonComponent Bean および Jackson Modules

  • Gson

  • Jsonb

@JsonTest によって有効にされる自動構成のリストは、付録に記載されています。

自動構成の要素を構成する必要がある場合は、@AutoConfigureJsonTesters アノテーションを使用できます。

Spring Boot には、JSONAssert および JsonPath ライブラリと連携して JSON が期待どおりに表示されることを確認する AssertJ ベースのヘルパーが含まれています。JacksonTesterGsonTesterJsonbTesterBasicJsonTester クラスは、それぞれ Jackson、Gson、Jsonb、Strings に使用できます。@JsonTest を使用する場合、テストクラスのヘルパーフィールドはすべて @Autowired にすることができます。次の例は、Jackson のテストクラスを示しています。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;

import static org.assertj.core.api.Assertions.assertThat;

@JsonTest
class MyJsonTests {

    @Autowired
    private JacksonTester<VehicleDetails> json;

    @Test
    void serialize() throws Exception {
        VehicleDetails details = new VehicleDetails("Honda", "Civic");
        // Assert against a `.json` file in the same package as the test
        assertThat(this.json.write(details)).isEqualToJson("expected.json");
        // Or use JSON path based assertions
        assertThat(this.json.write(details)).hasJsonPathStringValue("@.make");
        assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda");
    }

    @Test
    void deserialize() throws Exception {
        String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}";
        assertThat(this.json.parse(content)).isEqualTo(new VehicleDetails("Ford", "Focus"));
        assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.json.JsonTest
import org.springframework.boot.test.json.JacksonTester

@JsonTest
class MyJsonTests(@Autowired val json: JacksonTester<VehicleDetails>) {

    @Test
    fun serialize() {
        val details = VehicleDetails("Honda", "Civic")
        // Assert against a `.json` file in the same package as the test
        assertThat(json.write(details)).isEqualToJson("expected.json")
        // Or use JSON path based assertions
        assertThat(json.write(details)).hasJsonPathStringValue("@.make")
        assertThat(json.write(details)).extractingJsonPathStringValue("@.make").isEqualTo("Honda")
    }

    @Test
    fun deserialize() {
        val content = "{\"make\":\"Ford\",\"model\":\"Focus\"}"
        assertThat(json.parse(content)).isEqualTo(VehicleDetails("Ford", "Focus"))
        assertThat(json.parseObject(content).make).isEqualTo("Ford")
    }

}
JSON ヘルパークラスは、標準の単体テストで直接使用することもできます。これを行うには、@JsonTest を使用しない場合、@Before メソッドでヘルパーの initFields メソッドを呼び出します。

Spring Boot の AssertJ ベースのヘルパーを使用して特定の JSON パスの数値をアサートする場合、型によっては isEqualTo を使用できない場合があります。代わりに、AssertJ の satisfies を使用して、値が指定された条件に一致することを表明できます。たとえば、次の例では、実際の数値が 0.01 のオフセット内の 0.15 に近い浮動小数点値であると主張しています。

Java
@Test
void someTest() throws Exception {
    SomeObject value = new SomeObject(0.152f);
    assertThat(this.json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
        .satisfies((number) -> assertThat(number.floatValue()).isCloseTo(0.15f, within(0.01f)));
}
Kotlin
@Test
fun someTest() {
    val value = SomeObject(0.152f)
    assertThat(json.write(value)).extractingJsonPathNumberValue("@.test.numberValue")
        .satisfies(ThrowingConsumer { number ->
            assertThat(number.toFloat()).isCloseTo(0.15f, within(0.01f))
        })
}

9.3.16. 自動構成された Spring MVC テスト

Spring MVC コントローラーが期待どおりに機能しているかどうかをテストするには、@WebMvcTest アノテーションを使用します。@WebMvcTest は、Spring MVC インフラストラクチャを自動構成し、スキャンされた Bean を @Controller@ControllerAdvice@JsonComponentConverterGenericConverterFilterHandlerInterceptorWebMvcConfigurerWebMvcRegistrationsHandlerMethodArgumentResolver に制限します。@WebMvcTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。

@WebMvcTest によって有効にされる自動構成設定のリストは、付録に記載されています。
Jackson Module などの追加コンポーネントを登録する必要がある場合は、テストで @Import を使用して追加の構成クラスをインポートできます。

多くの場合、@WebMvcTest は単一のコントローラーに限定され、@MockBean と組み合わせて使用され、必要なコラボレーターにモック実装を提供します。

@WebMvcTest は MockMvc も自動構成します。Mock MVC は、完全な HTTP サーバーを起動する必要なく、MVC コントローラーをすばやくテストする強力な方法を提供します。

@AutoConfigureMockMvc でアノテーションを付けることにより、非 @WebMvcTest (@SpringBootTest など)で MockMvc を自動構成することもできます。次の例では、MockMvc を使用しています。
Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(UserVehicleController.class)
class MyControllerTests {

    @Autowired
    private MockMvc mvc;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot"))
            .willReturn(new VehicleDetails("Honda", "Civic"));
        this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andExpect(content().string("Honda Civic"));
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.http.MediaType
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers

@WebMvcTest(UserVehicleController::class)
class MyControllerTests(@Autowired val mvc: MockMvc) {

    @MockBean
    lateinit var userVehicleService: UserVehicleService

    @Test
    fun testExample() {
        given(userVehicleService.getVehicleDetails("sboot"))
            .willReturn(VehicleDetails("Honda", "Civic"))
        mvc.perform(MockMvcRequestBuilders.get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
            .andExpect(MockMvcResultMatchers.status().isOk)
            .andExpect(MockMvcResultMatchers.content().string("Honda Civic"))
    }

}
自動構成の要素を構成する必要がある場合(たとえば、サーブレットフィルターを適用する必要がある場合)、@AutoConfigureMockMvc アノテーションの属性を使用できます。

HtmlUnit および Selenium を使用する場合、自動構成は HtmlUnit WebClient Bean および / または Selenium WebDriver Bean も提供します。次の例では、HtmlUnit を使用しています。

Java
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;

@WebMvcTest(UserVehicleController.class)
class MyHtmlUnitTests {

    @Autowired
    private WebClient webClient;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void testExample() throws Exception {
        given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new VehicleDetails("Honda", "Civic"));
        HtmlPage page = this.webClient.getPage("/sboot/vehicle.html");
        assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic");
    }

}
Kotlin
import com.gargoylesoftware.htmlunit.WebClient
import com.gargoylesoftware.htmlunit.html.HtmlPage
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.boot.test.mock.mockito.MockBean

@WebMvcTest(UserVehicleController::class)
class MyHtmlUnitTests(@Autowired val webClient: WebClient) {

    @MockBean
    lateinit var userVehicleService: UserVehicleService

    @Test
    fun testExample() {
        given(userVehicleService.getVehicleDetails("sboot")).willReturn(VehicleDetails("Honda", "Civic"))
        val page = webClient.getPage<HtmlPage>("/sboot/vehicle.html")
        assertThat(page.body.textContent).isEqualTo("Honda Civic")
    }

}
デフォルトでは、Spring Boot は WebDriver Bean を特別な「スコープ」に配置して、各テストの後にドライバーが終了し、新しいインスタンスが注入されるようにします。この動作を望まない場合は、@Scope("singleton") を WebDriver @Bean 定義に追加できます。
Spring Boot によって作成された webDriver スコープは、同じ名前のユーザー定義スコープを置き換えます。独自の webDriver スコープを定義すると、@WebMvcTest を使用すると動作が停止する場合があります。

クラスパスに Spring Security がある場合、@WebMvcTest は WebSecurityConfigurer Bean もスキャンします。そのようなテストのセキュリティを完全に無効にする代わりに、Spring Security のテストサポートを使用できます。Spring Security の MockMvc サポートの使用方法の詳細については、この howto.html使い方セクションを参照してください。

Spring MVC テストを作成するだけでは不十分な場合があります。Spring Boot は、実際のサーバーで完全なエンドツーエンドテストを実行できます。

9.3.17. 自動構成された Spring WebFlux テスト

Spring WebFlux コントローラーが期待どおりに機能していることをテストするには、@WebFluxTest アノテーションを使用できます。@WebFluxTest は、Spring WebFlux インフラストラクチャを自動構成し、スキャンされた Bean を @Controller@ControllerAdvice@JsonComponentConverterGenericConverterWebFilterWebFluxConfigurer に制限します。@WebFluxTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。

@WebFluxTest によって有効にされる自動構成のリストは、付録に記載されています。
Jackson Module などの追加コンポーネントを登録する必要がある場合は、テストで @Import を使用して追加の構成クラスをインポートできます。

多くの場合、@WebFluxTest は単一のコントローラーに限定され、@MockBean アノテーションと組み合わせて使用され、必要なコラボレーターにモック実装を提供します。

@WebFluxTest は WebTestClient も自動構成します。これにより、完全な HTTP サーバーを起動する必要なく、WebFlux コントローラーを迅速にテストする強力な方法が提供されます。

@AutoConfigureWebTestClient でアノテーションを付けることにより、非 @WebFluxTest (@SpringBootTest など)で WebTestClient を自動構成することもできます。次の例は、@WebFluxTest と WebTestClient の両方を使用するクラスを示しています。
Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;

import static org.mockito.BDDMockito.given;

@WebFluxTest(UserVehicleController.class)
class MyControllerTests {

    @Autowired
    private WebTestClient webClient;

    @MockBean
    private UserVehicleService userVehicleService;

    @Test
    void testExample() {
        given(this.userVehicleService.getVehicleDetails("sboot"))
            .willReturn(new VehicleDetails("Honda", "Civic"));
        this.webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange()
            .expectStatus().isOk()
            .expectBody(String.class).isEqualTo("Honda Civic");
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.mockito.BDDMockito.given
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.http.MediaType
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.test.web.reactive.server.expectBody

@WebFluxTest(UserVehicleController::class)
class MyControllerTests(@Autowired val webClient: WebTestClient) {

    @MockBean
    lateinit var userVehicleService: UserVehicleService

    @Test
    fun testExample() {
        given(userVehicleService.getVehicleDetails("sboot"))
            .willReturn(VehicleDetails("Honda", "Civic"))
        webClient.get().uri("/sboot/vehicle").accept(MediaType.TEXT_PLAIN).exchange()
            .expectStatus().isOk
            .expectBody<String>().isEqualTo("Honda Civic")
    }

}
モック Web アプリケーションで WebTestClient を使用するのは、現時点では WebFlux でのみ機能するため、このセットアップは WebFlux アプリケーションでのみサポートされます。
@WebFluxTest は、機能する Web フレームワークを介して登録されたルートを検出できません。コンテキストで RouterFunction Bean をテストするには、@Import または @SpringBootTest を使用して RouterFunction を自分でインポートすることを検討してください。
@WebFluxTest は、型 SecurityWebFilterChain の @Bean として登録されているカスタムセキュリティ構成を検出できません。これをテストに含めるには、@Import または @SpringBootTest を使用して、Bean を登録する構成をインポートする必要があります。
Spring WebFlux テストを書くだけでは十分でない場合があります。Spring Boot は、実際のサーバーで完全なエンドツーエンドテストを実行するのに役立ちます。

9.3.18. 自動構成された Spring GraphQL テスト

Spring GraphQL は、専用のテストサポートモジュールを提供します。プロジェクトに追加する必要があります。

Maven
<dependencies>
  <dependency>
    <groupId>org.springframework.graphql</groupId>
    <artifactId>spring-graphql-test</artifactId>
    <scope>test</scope>
  </dependency>
  <!-- Unless already present in the compile scope -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>
Gradle
dependencies {
  testImplementation("org.springframework.graphql:spring-graphql-test")
  // Unless already present in the implementation configuration
  testImplementation("org.springframework.boot:spring-boot-starter-webflux")
}

このテストモジュールは GraphQlTester を提供します。テスターはテストで頻繁に使用されるため、必ず使用に慣れてください。GraphQlTester バリアントがあり、Spring Boot はテストの型に応じて自動構成します。

  • ExecutionGraphQlServiceTester は、クライアントもトランスポートも使用せずに、サーバー側でテストを実行します

  • HttpGraphQlTester は、ライブサーバーの有無にかかわらず、サーバーに接続するクライアントでテストを実行します

Spring Boot は、@GraphQlTest アノテーションを使用して Spring GraphQL コントローラーをテストできます。@GraphQlTest は、トランスポートやサーバーを使用せずに、Spring GraphQL インフラストラクチャを自動構成します。これにより、スキャンされた Bean が @ControllerRuntimeWiringConfigurerJsonComponentConverterGenericConverterDataFetcherExceptionResolverInstrumentationGraphQlSourceBuilderCustomizer に制限されます。@GraphQlTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。

@GraphQlTest によって有効にされる自動構成のリストは、付録に記載されています。

多くの場合、@GraphQlTest は一連のコントローラーに限定され、@MockBean アノテーションと組み合わせて使用され、必要なコラボレーターにモック実装を提供します。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.docs.web.graphql.runtimewiring.GreetingController;
import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest;
import org.springframework.graphql.test.tester.GraphQlTester;

@GraphQlTest(GreetingController.class)
class GreetingControllerTests {

    @Autowired
    private GraphQlTester graphQlTester;

    @Test
    void shouldGreetWithSpecificName() {
        this.graphQlTester.document("{ greeting(name: \"Alice\") } ")
            .execute()
            .path("greeting")
            .entity(String.class)
            .isEqualTo("Hello, Alice!");
    }

    @Test
    void shouldGreetWithDefaultName() {
        this.graphQlTester.document("{ greeting } ")
            .execute()
            .path("greeting")
            .entity(String.class)
            .isEqualTo("Hello, Spring!");
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.docs.web.graphql.runtimewiring.GreetingController
import org.springframework.boot.test.autoconfigure.graphql.GraphQlTest
import org.springframework.graphql.test.tester.GraphQlTester

@GraphQlTest(GreetingController::class)
internal class GreetingControllerTests {

    @Autowired
    lateinit var graphQlTester: GraphQlTester

    @Test
    fun shouldGreetWithSpecificName() {
        graphQlTester.document("{ greeting(name: \"Alice\") } ").execute().path("greeting").entity(String::class.java)
                .isEqualTo("Hello, Alice!")
    }

    @Test
    fun shouldGreetWithDefaultName() {
        graphQlTester.document("{ greeting } ").execute().path("greeting").entity(String::class.java)
                .isEqualTo("Hello, Spring!")
    }

}

@SpringBootTest テストは完全な統合テストであり、アプリケーション全体が関与します。ランダムポートまたは定義済みポートを使用する場合、ライブサーバーが構成され、HttpGraphQlTester Bean が自動的に提供されるため、サーバーのテストに使用できます。MOCK 環境が構成されている場合、テストクラスに @AutoConfigureHttpGraphQlTester アノテーションを付けることで、HttpGraphQlTester Bean をリクエストすることもできます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureHttpGraphQlTester;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.graphql.test.tester.HttpGraphQlTester;

@AutoConfigureHttpGraphQlTester
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class GraphQlIntegrationTests {

    @Test
    void shouldGreetWithSpecificName(@Autowired HttpGraphQlTester graphQlTester) {
        HttpGraphQlTester authenticatedTester = graphQlTester.mutate()
            .webTestClient((client) -> client.defaultHeaders((headers) -> headers.setBasicAuth("admin", "ilovespring")))
            .build();
        authenticatedTester.document("{ greeting(name: \"Alice\") } ")
            .execute()
            .path("greeting")
            .entity(String.class)
            .isEqualTo("Hello, Alice!");
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.graphql.tester.AutoConfigureHttpGraphQlTester
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.graphql.test.tester.HttpGraphQlTester
import org.springframework.http.HttpHeaders
import org.springframework.test.web.reactive.server.WebTestClient

@AutoConfigureHttpGraphQlTester
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class GraphQlIntegrationTests {

    @Test
    fun shouldGreetWithSpecificName(@Autowired graphQlTester: HttpGraphQlTester) {
        val authenticatedTester = graphQlTester.mutate()
            .webTestClient { client: WebTestClient.Builder ->
                client.defaultHeaders { headers: HttpHeaders ->
                    headers.setBasicAuth("admin", "ilovespring")
                }
            }.build()
        authenticatedTester.document("{ greeting(name: \"Alice\") } ").execute()
            .path("greeting").entity(String::class.java).isEqualTo("Hello, Alice!")
    }
}

9.3.19. 自動構成された Data Cassandra テスト

@DataCassandraTest を使用して、Cassandra アプリケーションをテストできます。デフォルトでは、CassandraTemplate を構成し、@Table クラスをスキャンし、Spring Data Cassandra リポジトリを構成します。@DataCassandraTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。(Spring Boot で Cassandra を使用する方法の詳細については、"data.html" を参照してください。)

@DataCassandraTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、Spring Boot で Cassandra テストを使用するための一般的なセットアップを示しています。

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest;

@DataCassandraTest
class MyDataCassandraTests {

    @Autowired
    private SomeRepository repository;

}
Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.cassandra.DataCassandraTest

@DataCassandraTest
class MyDataCassandraTests(@Autowired val repository: SomeRepository)

9.3.20. 自動構成された Data Couchbase テスト

@DataCouchbaseTest を使用して Couchbase アプリケーションをテストできます。デフォルトでは、CouchbaseTemplate または ReactiveCouchbaseTemplate を構成し、@Document クラスをスキャンし、Spring Data Couchbase リポジトリを構成します。@DataCouchbaseTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。(Couchbase を Spring Boot とともに使用する方法の詳細については、この章で前述した "data.html" を参照してください。)

@DataCouchbaseTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、Spring Boot で Couchbase テストを使用するための一般的なセットアップを示しています。

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.couchbase.DataCouchbaseTest;

@DataCouchbaseTest
class MyDataCouchbaseTests {

    @Autowired
    private SomeRepository repository;

    // ...

}
Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.couchbase.DataCouchbaseTest

@DataCouchbaseTest
class MyDataCouchbaseTests(@Autowired val repository: SomeRepository) {

    // ...

}

9.3.21. 自動構成された Data Elasticsearch テスト

@DataElasticsearchTest を使用して Elasticsearch アプリケーションをテストできます。デフォルトでは、ElasticsearchRestTemplate を構成し、@Document クラスをスキャンし、Spring Data Elasticsearch リポジトリを構成します。@DataElasticsearchTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties を使用して @ConfigurationProperties Bean を含めることができます。(Elasticsearch を Spring Boot とともに使用する方法の詳細については、この章で前述した "data.html" を参照してください。)

@DataElasticsearchTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、Spring Boot で Elasticsearch テストを使用するための一般的なセットアップを示しています。

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest;

@DataElasticsearchTest
class MyDataElasticsearchTests {

    @Autowired
    private SomeRepository repository;

    // ...

}
Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.elasticsearch.DataElasticsearchTest

@DataElasticsearchTest
class MyDataElasticsearchTests(@Autowired val repository: SomeRepository) {

    // ...

}

9.3.22. 自動構成された Data JPA テスト

@DataJpaTest アノテーションを使用して JPA アプリケーションをテストできます。デフォルトでは、@Entity クラスをスキャンし、Spring Data JPA リポジトリを構成します。組み込みデータベースがクラスパスで使用可能な場合は、それも構成します。SQL クエリは、spring.jpa.show-sql プロパティを true に設定することにより、デフォルトでログに記録されます。これは、アノテーションの showSql 属性を使用して無効にできます。

@DataJpaTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。

@DataJpaTest によって有効にされる自動構成設定のリストは、付録に記載されています。

デフォルトでは、Data JPA テストはトランザクションであり、各テストの終了時にロールバックされます。詳細については、Spring Framework リファレンスドキュメントの関連セクションを参照してください。それが望んでいない場合、次のようにテストまたはクラス全体のトランザクション管理を無効にできます。

Java
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {

    // ...

}
Kotlin
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional

@DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {

    // ...

}

Data JPA テストでは、TestEntityManager [GitHub] (英語) Bean を挿入することもできます。これは、テスト用に特別に設計された標準の JPA EntityManager の代替手段を提供します。

TestEntityManager は、@AutoConfigureTestEntityManager を追加することにより、Spring ベースのテストクラスのいずれかに自動構成することもできます。その際、テストクラスまたはメソッドに @Transactional を追加するなどして、テストがトランザクションで実行されていることを確認してください。

必要に応じて、JdbcTemplate も利用できます。次の例は、使用中の @DataJpaTest アノテーションを示しています。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;

import static org.assertj.core.api.Assertions.assertThat;

@DataJpaTest
class MyRepositoryTests {

    @Autowired
    private TestEntityManager entityManager;

    @Autowired
    private UserRepository repository;

    @Test
    void testExample() {
        this.entityManager.persist(new User("sboot", "1234"));
        User user = this.repository.findByUsername("sboot");
        assertThat(user.getUsername()).isEqualTo("sboot");
        assertThat(user.getEmployeeNumber()).isEqualTo("1234");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager

@DataJpaTest
class MyRepositoryTests(@Autowired val entityManager: TestEntityManager, @Autowired val repository: UserRepository) {

    @Test
    fun testExample() {
        entityManager.persist(User("sboot", "1234"))
        val user = repository.findByUsername("sboot")
        assertThat(user?.username).isEqualTo("sboot")
        assertThat(user?.employeeNumber).isEqualTo("1234")
    }

}

メモリ内の組み込みデータベースは、高速でインストールを必要としないため、一般にテストに適しています。ただし、次の例に示すように、実際のデータベースに対してテストを実行する場合は、@AutoConfigureTestDatabase アノテーションを使用できます。

Java
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;

@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
class MyRepositoryTests {

    // ...

}
Kotlin
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest

@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class MyRepositoryTests {

    // ...

}

9.3.23. 自動構成された JDBC テスト

@JdbcTest は @DataJpaTest に似ていますが、DataSource のみを必要とし、Spring Data JDBC を使用しないテスト用です。デフォルトでは、メモリ内埋め込みデータベースと JdbcTemplate を構成します。@JdbcTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties を使用して、@ConfigurationProperties Bean を含めることができます。

@JdbcTest によって有効にされる自動構成のリストは、付録に記載されています。

デフォルトでは、JDBC テストはトランザクション対応であり、各テストの終わりにロールバックします。詳細については、Spring Framework リファレンスドキュメントの関連セクションを参照してください。それが望んでいない場合は、次のように、テストまたはクラス全体のトランザクション管理を無効にできます。

Java
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests {

}
Kotlin
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional

@JdbcTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyTransactionalTests

テストを実際のデータベースに対して実行したい場合は、@DataJpaTest と同じ方法で @AutoConfigureTestDatabase アノテーションを使用できます。( "自動構成された Data JPA テスト" を参照してください。)

9.3.24. 自動構成された Data JDBC テスト

@DataJdbcTest は @JdbcTest に似ていますが、Spring Data JDBC リポジトリを使用するテスト用です。デフォルトでは、インメモリ組み込みデータベース、JdbcTemplate、Spring Data JDBC リポジトリが構成されます。@DataJdbcTest アノテーションが使用されている場合、AbstractJdbcConfiguration サブクラスのみがスキャンされ、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties を使用して、@ConfigurationProperties Bean を組み込むことができます。

@DataJdbcTest によって有効にされる自動構成のリストは、付録に記載されています。

デフォルトでは、Data JDBC テストはトランザクションであり、各テストの終了時にロールバックされます。詳細については、Spring Framework リファレンスドキュメントの関連セクションを参照してください。それが望んでいない場合、JDBC の例に示すように、テストまたはテストクラス全体のトランザクション管理を無効にすることができます。

テストを実際のデータベースに対して実行したい場合は、@DataJpaTest と同じ方法で @AutoConfigureTestDatabase アノテーションを使用できます。( "自動構成された Data JPA テスト" を参照してください。)

9.3.25. 自動構成された Data R2DBC テスト

@DataR2dbcTest は @DataJdbcTest に似ていますが、Spring Data R2DBC リポジトリを使用するテスト用です。デフォルトでは、インメモリ組み込みデータベース、R2dbcEntityTemplate、Spring Data R2DBC リポジトリが構成されます。@DataR2dbcTest アノテーションが使用されている場合、通常の @Component Bean および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties を使用して、@ConfigurationProperties Bean を含めることができます。

@DataR2dbcTest によって有効にされる自動構成のリストは、付録に記載されています。

デフォルトでは、データ R2DBC テストはトランザクションではありません。

テストを実際のデータベースに対して実行したい場合は、@DataJpaTest と同じ方法で @AutoConfigureTestDatabase アノテーションを使用できます。( "自動構成された Data JPA テスト" を参照してください。)

9.3.26. 自動構成された jOOQ テスト

@JooqTest は、@JdbcTest と同様の方法で使用できますが、jOOQ 関連のテストに使用できます。jOOQ はデータベーススキーマに対応する Java ベースのスキーマに大きく依存しているため、既存の DataSource が使用されます。インメモリデータベースに置き換える場合は、@AutoConfigureTestDatabase を使用してこれらの設定を上書きできます。(Spring Boot での jOOQ の使用の詳細については、"data.html" を参照してください) @JooqTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。

@JooqTest によって有効にされる自動構成のリストは、付録に記載されています。

@JooqTest は DSLContext を構成します。次の例は、使用中の @JooqTest アノテーションを示しています。

Java
import org.jooq.DSLContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jooq.JooqTest;

@JooqTest
class MyJooqTests {

    @Autowired
    private DSLContext dslContext;

    // ...

}
Kotlin
import org.jooq.DSLContext
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.jooq.JooqTest

@JooqTest
class MyJooqTests(@Autowired val dslContext: DSLContext) {

    // ...

}

JOOQ テストはトランザクション対応であり、デフォルトでは各テストの終わりにロールバックします。それが望んでいない場合、JDBC の例に示すように、テストまたはテストクラス全体のトランザクション管理を無効にすることができます。

9.3.27. 自動構成された Data MongoDB テスト

@DataMongoTest を使用して MongoDB アプリケーションをテストできます。デフォルトでは、MongoTemplate を構成し、@Document クラスをスキャンし、Spring Data MongoDB リポジトリを構成します。@DataMongoTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。(Spring Boot での MongoDB の使用の詳細については、"data.html" を参照してください。)

@DataMongoTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次のクラスは、使用中の @DataMongoTest アノテーションを示しています。

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest;
import org.springframework.data.mongodb.core.MongoTemplate;

@DataMongoTest
class MyDataMongoDbTests {

    @Autowired
    private MongoTemplate mongoTemplate;

    // ...

}
Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest
import org.springframework.data.mongodb.core.MongoTemplate

@DataMongoTest
class MyDataMongoDbTests(@Autowired val mongoTemplate: MongoTemplate) {

    // ...

}

9.3.28. 自動構成された Data Neo4j テスト

@DataNeo4jTest を使用して Neo4j アプリケーションをテストできます。デフォルトでは、@Node クラスをスキャンし、Spring Data Neo4j リポジトリを構成します。@DataNeo4jTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties は、@ConfigurationProperties Bean を含めるために使用できます。(Spring Boot での Neo4J の使用の詳細については、"data.html" を参照してください。)

@DataNeo4jTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、Spring Boot で Neo4J テストを使用するための一般的なセットアップを示しています。

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;

@DataNeo4jTest
class MyDataNeo4jTests {

    @Autowired
    private SomeRepository repository;

    // ...

}
Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest

@DataNeo4jTest
class MyDataNeo4jTests(@Autowired val repository: SomeRepository) {

    // ...

}

デフォルトでは、Data Neo4j テストはトランザクション対応であり、各テストの終わりにロールバックします。詳細については、Spring Framework リファレンスドキュメントの関連セクションを参照してください。それが望んでいない場合は、次のように、テストまたはクラス全体のトランザクション管理を無効にできます。

Java
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyDataNeo4jTests {

}
Kotlin
import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional

@DataNeo4jTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyDataNeo4jTests
トランザクションテストは、リアクティブアクセスではサポートされていません。このスタイルを使用している場合は、上記のように @DataNeo4jTest テストを構成する必要があります。

9.3.29. 自動構成された Data Redis テスト

@DataRedisTest を使用して Redis アプリケーションをテストできます。デフォルトでは、@RedisHash クラスをスキャンし、Spring Data Redis リポジトリを構成します。@DataRedisTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties を使用して、@ConfigurationProperties Bean を含めることができます。(Spring Boot で Redis を使用する方法の詳細については、"data.html" を参照してください。)

@DataRedisTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、使用中の @DataRedisTest アノテーションを示しています。

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest;

@DataRedisTest
class MyDataRedisTests {

    @Autowired
    private SomeRepository repository;

    // ...

}
Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.redis.DataRedisTest

@DataRedisTest
class MyDataRedisTests(@Autowired val repository: SomeRepository) {

    // ...

}

9.3.30. 自動構成された Data LDAP テスト

@DataLdapTest を使用して LDAP アプリケーションをテストできます。デフォルトでは、インメモリ組み込み LDAP(使用可能な場合)を構成し、LdapTemplate を構成し、@Entry クラスをスキャンし、Spring Data LDAP リポジトリを構成します。@DataLdapTest アノテーションが使用されている場合、通常の @Component および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties を使用して、@ConfigurationProperties Bean を含めることができます。(Spring Boot での LDAP の使用の詳細については、"data.html" を参照してください。)

@DataLdapTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、使用中の @DataLdapTest アノテーションを示しています。

Java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;
import org.springframework.ldap.core.LdapTemplate;

@DataLdapTest
class MyDataLdapTests {

    @Autowired
    private LdapTemplate ldapTemplate;

    // ...

}
Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest
import org.springframework.ldap.core.LdapTemplate

@DataLdapTest
class MyDataLdapTests(@Autowired val ldapTemplate: LdapTemplate) {

    // ...

}

メモリ内の組み込み LDAP は、高速であり、開発者がインストールする必要がないため、一般にテストに適しています。ただし、実際の LDAP サーバーに対してテストを実行する場合は、次の例に示すように、組み込みの LDAP 自動構成を除外する必要があります。

Java
import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration;
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest;

@DataLdapTest(excludeAutoConfiguration = EmbeddedLdapAutoConfiguration.class)
class MyDataLdapTests {

    // ...

}
Kotlin
import org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration
import org.springframework.boot.test.autoconfigure.data.ldap.DataLdapTest

@DataLdapTest(excludeAutoConfiguration = [EmbeddedLdapAutoConfiguration::class])
class MyDataLdapTests {

    // ...

}

9.3.31. 自動構成された REST クライアント

@RestClientTest アノテーションを使用して、REST クライアントをテストできます。デフォルトでは、Jackson、GSON、Jsonb のサポートが自動構成され、RestTemplateBuilder および RestClient.Builder が構成され、MockRestServiceServer のサポートが追加されます。@RestClientTest アノテーションが使用されている場合、通常の @Component Bean および @ConfigurationProperties Bean はスキャンされません。@EnableConfigurationProperties を使用して、@ConfigurationProperties Bean を含めることができます。

@RestClientTest によって有効にされる自動構成設定のリストは、付録に記載されています。

テストする特定の Bean は、@RestClientTest の value または components 属性を使用して指定する必要があります。

テスト対象の Bean で RestTemplateBuilder を使用し、RestTemplate の構築時に RestTemplateBuilder.rootUri(String rootUri) が呼び出された場合、次の例に示すように、ルート URI を MockRestServiceServer の期待値から省略する必要があります。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;

@RestClientTest(RemoteVehicleDetailsService.class)
class MyRestTemplateServiceTests {

    @Autowired
    private RemoteVehicleDetailsService service;

    @Autowired
    private MockRestServiceServer server;

    @Test
    void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
        this.server.expect(requestTo("/greet/details")).andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
        String greeting = this.service.callRestService();
        assertThat(greeting).isEqualTo("hello");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest
import org.springframework.http.MediaType
import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.match.MockRestRequestMatchers
import org.springframework.test.web.client.response.MockRestResponseCreators

@RestClientTest(RemoteVehicleDetailsService::class)
class MyRestTemplateServiceTests(
    @Autowired val service: RemoteVehicleDetailsService,
    @Autowired val server: MockRestServiceServer) {

    @Test
    fun getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
        server.expect(MockRestRequestMatchers.requestTo("/greet/details"))
            .andRespond(MockRestResponseCreators.withSuccess("hello", MediaType.TEXT_PLAIN))
        val greeting = service.callRestService()
        assertThat(greeting).isEqualTo("hello")
    }

}

テスト対象の Bean で RestClient.Builder を使用する場合、または rootUri(String rootURI) を呼び出さずに RestTemplateBuilder を使用する場合、次の例に示すように、完全な URI を MockRestServiceServer の期待値で使用する必要があります。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.client.MockRestServiceServer;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;

@RestClientTest(RemoteVehicleDetailsService.class)
class MyRestClientServiceTests {

    @Autowired
    private RemoteVehicleDetailsService service;

    @Autowired
    private MockRestServiceServer server;

    @Test
    void getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
        this.server.expect(requestTo("https://example.com/greet/details"))
            .andRespond(withSuccess("hello", MediaType.TEXT_PLAIN));
        String greeting = this.service.callRestService();
        assertThat(greeting).isEqualTo("hello");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.client.RestClientTest
import org.springframework.http.MediaType
import org.springframework.test.web.client.MockRestServiceServer
import org.springframework.test.web.client.match.MockRestRequestMatchers
import org.springframework.test.web.client.response.MockRestResponseCreators

@RestClientTest(RemoteVehicleDetailsService::class)
class MyRestClientServiceTests(
    @Autowired val service: RemoteVehicleDetailsService,
    @Autowired val server: MockRestServiceServer) {

    @Test
    fun getVehicleDetailsWhenResultIsSuccessShouldReturnDetails() {
        server.expect(MockRestRequestMatchers.requestTo("https://example.com/greet/details"))
            .andRespond(MockRestResponseCreators.withSuccess("hello", MediaType.TEXT_PLAIN))
        val greeting = service.callRestService()
        assertThat(greeting).isEqualTo("hello")
    }

}

9.3.32. 自動構成された Spring REST Docs テスト

@AutoConfigureRestDocs アノテーションを使用して、Mock MVC、REST Assured、または WebTestClient を使用したテストで Spring REST Docs を使用できます。Spring REST Docs の JUnit 拡張機能の必要性がなくなります。

@AutoConfigureRestDocs を使用して、デフォルトの出力ディレクトリをオーバーライドできます(Maven を使用している場合は target/generated-snippets、Gradle を使用している場合は build/generated-snippets)。また、ドキュメント化された URI に表示されるホスト、スキーム、ポートの構成にも使用できます。

モック MVC を使用した自動構成 Spring REST Docs テスト

@AutoConfigureRestDocs は、サーブレットベースの Web アプリケーションをテストするときに Spring REST Docs を使用するように MockMvc Bean をカスタマイズします。次の例に示すように、@Autowired を使用して注入し、モック MVC と Spring REST Docs を使用する場合と同じようにテストで使用できます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest(UserController.class)
@AutoConfigureRestDocs
class MyUserDocumentationTests {

    @Autowired
    private MockMvc mvc;

    @Test
    void listUsers() throws Exception {
        this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
            .andExpect(status().isOk())
            .andDo(document("list-users"));
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.http.MediaType
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders
import org.springframework.test.web.servlet.result.MockMvcResultMatchers

@WebMvcTest(UserController::class)
@AutoConfigureRestDocs
class MyUserDocumentationTests(@Autowired val mvc: MockMvc) {

    @Test
    fun listUsers() {
        mvc.perform(MockMvcRequestBuilders.get("/users").accept(MediaType.TEXT_PLAIN))
            .andExpect(MockMvcResultMatchers.status().isOk)
            .andDo(MockMvcRestDocumentation.document("list-users"))
    }

}

@AutoConfigureRestDocs の属性で提供されるよりも Spring REST Docs 構成をより詳細に制御する必要がある場合は、次の例に示すように、RestDocsMockMvcConfigurationCustomizer Bean を使用できます。

Java
import org.springframework.boot.test.autoconfigure.restdocs.RestDocsMockMvcConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer;
import org.springframework.restdocs.templates.TemplateFormats;

@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsMockMvcConfigurationCustomizer {

    @Override
    public void customize(MockMvcRestDocumentationConfigurer configurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
    }

}
Kotlin
import org.springframework.boot.test.autoconfigure.restdocs.RestDocsMockMvcConfigurationCustomizer
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer
import org.springframework.restdocs.templates.TemplateFormats

@TestConfiguration(proxyBeanMethods = false)
class MyRestDocsConfiguration : RestDocsMockMvcConfigurationCustomizer {

    override fun customize(configurer: MockMvcRestDocumentationConfigurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown())
    }

}

パラメーター化された出力ディレクトリの Spring REST Docs サポートを利用する場合は、RestDocumentationResultHandler Bean を作成できます。自動構成は、この結果ハンドラーを使用して alwaysDo を呼び出します。これにより、各 MockMvc 呼び出しでデフォルトのスニペットが自動的に生成されます。次の例は、定義されている RestDocumentationResultHandler を示しています。

Java
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation;
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler;

@TestConfiguration(proxyBeanMethods = false)
public class MyResultHandlerConfiguration {

    @Bean
    public RestDocumentationResultHandler restDocumentation() {
        return MockMvcRestDocumentation.document("{method-name}");
    }

}
Kotlin
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.restdocs.mockmvc.MockMvcRestDocumentation
import org.springframework.restdocs.mockmvc.RestDocumentationResultHandler

@TestConfiguration(proxyBeanMethods = false)
class MyResultHandlerConfiguration {

    @Bean
    fun restDocumentation(): RestDocumentationResultHandler {
        return MockMvcRestDocumentation.document("{method-name}")
    }

}
WebTestClient を使用した自動構成 Spring REST Docs テスト

@AutoConfigureRestDocs は、リアクティブ Web アプリケーションをテストするときに WebTestClient と共に使用することもできます。次の例に示すように、@Autowired を使用して注入し、@WebFluxTest および Spring REST Docs を使用する場合と同じようにテストで使用できます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
import org.springframework.test.web.reactive.server.WebTestClient;

import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;

@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests {

    @Autowired
    private WebTestClient webTestClient;

    @Test
    void listUsers() {
        this.webTestClient
            .get().uri("/")
        .exchange()
        .expectStatus()
            .isOk()
        .expectBody()
            .consumeWith(document("list-users"));
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs
import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
import org.springframework.test.web.reactive.server.WebTestClient

@WebFluxTest
@AutoConfigureRestDocs
class MyUsersDocumentationTests(@Autowired val webTestClient: WebTestClient) {

    @Test
    fun listUsers() {
        webTestClient
            .get().uri("/")
            .exchange()
            .expectStatus()
            .isOk
            .expectBody()
            .consumeWith(WebTestClientRestDocumentation.document("list-users"))
    }

}

@AutoConfigureRestDocs の属性で提供されるよりも Spring REST Docs 構成をより詳細に制御する必要がある場合は、次の例に示すように、RestDocsWebTestClientConfigurationCustomizer Bean を使用できます。

Java
import org.springframework.boot.test.autoconfigure.restdocs.RestDocsWebTestClientConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer;

@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsWebTestClientConfigurationCustomizer {

    @Override
    public void customize(WebTestClientRestDocumentationConfigurer configurer) {
        configurer.snippets().withEncoding("UTF-8");
    }

}
Kotlin
import org.springframework.boot.test.autoconfigure.restdocs.RestDocsWebTestClientConfigurationCustomizer
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer

@TestConfiguration(proxyBeanMethods = false)
class MyRestDocsConfiguration : RestDocsWebTestClientConfigurationCustomizer {

    override fun customize(configurer: WebTestClientRestDocumentationConfigurer) {
        configurer.snippets().withEncoding("UTF-8")
    }

}

パラメーター化された出力ディレクトリに対して Spring REST Docs サポートを利用する場合は、WebTestClientBuilderCustomizer を使用して、すべてのエンティティ交換結果のコンシューマーを構成できます。次の例は、そのような WebTestClientBuilderCustomizer が定義されていることを示しています。

Java
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.reactive.server.WebTestClientBuilderCustomizer;
import org.springframework.context.annotation.Bean;

import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document;

@TestConfiguration(proxyBeanMethods = false)
public class MyWebTestClientBuilderCustomizerConfiguration {

    @Bean
    public WebTestClientBuilderCustomizer restDocumentation() {
        return (builder) -> builder.entityExchangeResultConsumer(document("{method-name}"));
    }

}
Kotlin
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.test.web.reactive.server.WebTestClientBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation
import org.springframework.test.web.reactive.server.WebTestClient

@TestConfiguration(proxyBeanMethods = false)
class MyWebTestClientBuilderCustomizerConfiguration {

    @Bean
    fun restDocumentation(): WebTestClientBuilderCustomizer {
        return WebTestClientBuilderCustomizer { builder: WebTestClient.Builder ->
            builder.entityExchangeResultConsumer(
                WebTestClientRestDocumentation.document("{method-name}")
            )
        }
    }

}
REST が保証された自動構成 Spring REST Docs テスト

@AutoConfigureRestDocs は、Spring REST Docs を使用するように事前構成された RequestSpecification Bean をテストで使用できるようにします。次の例に示すように、REST Assured および Spring REST Docs を使用する場合と同様に、@Autowired を使用して注入し、テストで使用できます。

Java
import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.server.LocalServerPort;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.is;
import static org.springframework.restdocs.restassured.RestAssuredRestDocumentation.document;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
class MyUserDocumentationTests {

    @Test
    void listUsers(@Autowired RequestSpecification documentationSpec, @LocalServerPort int port) {
        given(documentationSpec)
            .filter(document("list-users"))
        .when()
            .port(port)
            .get("/")
        .then().assertThat()
            .statusCode(is(200));
    }

}
Kotlin
import io.restassured.RestAssured
import io.restassured.specification.RequestSpecification
import org.hamcrest.Matchers
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.boot.test.web.server.LocalServerPort
import org.springframework.restdocs.restassured.RestAssuredRestDocumentation

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureRestDocs
class MyUserDocumentationTests {

    @Test
    fun listUsers(@Autowired documentationSpec: RequestSpecification?, @LocalServerPort port: Int) {
        RestAssured.given(documentationSpec)
            .filter(RestAssuredRestDocumentation.document("list-users"))
            .`when`()
            .port(port)["/"]
            .then().assertThat()
            .statusCode(Matchers.`is`(200))
    }

}

@AutoConfigureRestDocs の属性で提供されるよりも Spring REST Docs 構成をより詳細に制御する必要がある場合、次の例に示すように、RestDocsRestAssuredConfigurationCustomizer Bean を使用できます。

Java
import org.springframework.boot.test.autoconfigure.restdocs.RestDocsRestAssuredConfigurationCustomizer;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer;
import org.springframework.restdocs.templates.TemplateFormats;

@TestConfiguration(proxyBeanMethods = false)
public class MyRestDocsConfiguration implements RestDocsRestAssuredConfigurationCustomizer {

    @Override
    public void customize(RestAssuredRestDocumentationConfigurer configurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown());
    }

}
Kotlin
import org.springframework.boot.test.autoconfigure.restdocs.RestDocsRestAssuredConfigurationCustomizer
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.restdocs.restassured.RestAssuredRestDocumentationConfigurer
import org.springframework.restdocs.templates.TemplateFormats

@TestConfiguration(proxyBeanMethods = false)
class MyRestDocsConfiguration : RestDocsRestAssuredConfigurationCustomizer {

    override fun customize(configurer: RestAssuredRestDocumentationConfigurer) {
        configurer.snippets().withTemplateFormat(TemplateFormats.markdown())
    }

}

9.3.33. 自動構成された Spring Web Services テスト

自動構成された Spring Web Services クライアントテスト

@WebServiceClientTest を使用して、Spring Web Services プロジェクトを使用して Web サービスを呼び出すアプリケーションをテストできます。デフォルトでは、モック WebServiceServer Bean を構成し、WebServiceTemplateBuilder を自動的にカスタマイズします。(Spring Boot での Web サービスの使用の詳細については、"io.html" を参照してください。)

@WebServiceClientTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、使用中の @WebServiceClientTest アノテーションを示しています。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.webservices.client.WebServiceClientTest;
import org.springframework.ws.test.client.MockWebServiceServer;
import org.springframework.xml.transform.StringSource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.ws.test.client.RequestMatchers.payload;
import static org.springframework.ws.test.client.ResponseCreators.withPayload;

@WebServiceClientTest(SomeWebService.class)
class MyWebServiceClientTests {

    @Autowired
    private MockWebServiceServer server;

    @Autowired
    private SomeWebService someWebService;

    @Test
    void mockServerCall() {
        this.server
            .expect(payload(new StringSource("<request/>")))
            .andRespond(withPayload(new StringSource("<response><status>200</status></response>")));
        assertThat(this.someWebService.test())
            .extracting(Response::getStatus)
            .isEqualTo(200);
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.webservices.client.WebServiceClientTest
import org.springframework.ws.test.client.MockWebServiceServer
import org.springframework.ws.test.client.RequestMatchers
import org.springframework.ws.test.client.ResponseCreators
import org.springframework.xml.transform.StringSource

@WebServiceClientTest(SomeWebService::class)
class MyWebServiceClientTests(@Autowired val server: MockWebServiceServer, @Autowired val someWebService: SomeWebService) {

    @Test
    fun mockServerCall() {
        server
            .expect(RequestMatchers.payload(StringSource("<request/>")))
            .andRespond(ResponseCreators.withPayload(StringSource("<response><status>200</status></response>")))
        assertThat(this.someWebService.test()).extracting(Response::status).isEqualTo(200)
    }

}
自動構成された Spring Web Services サーバーテスト

@WebServiceServerTest を使用して、Spring Web Services プロジェクトを使用して Web サービスを実装するアプリケーションをテストできます。デフォルトでは、Web サービスエンドポイントの呼び出しに使用できる MockWebServiceClient Bean を構成します。(Spring Boot での Web サービスの使用の詳細については、"io.html" を参照してください。)

@WebServiceServerTest によって有効にされる自動構成設定のリストは、付録に記載されています。

次の例は、使用中の @WebServiceServerTest アノテーションを示しています。

Java
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.webservices.server.WebServiceServerTest;
import org.springframework.ws.test.server.MockWebServiceClient;
import org.springframework.ws.test.server.RequestCreators;
import org.springframework.ws.test.server.ResponseMatchers;
import org.springframework.xml.transform.StringSource;

@WebServiceServerTest(ExampleEndpoint.class)
class MyWebServiceServerTests {

    @Autowired
    private MockWebServiceClient client;

    @Test
    void mockServerCall() {
        this.client
            .sendRequest(RequestCreators.withPayload(new StringSource("<ExampleRequest/>")))
            .andExpect(ResponseMatchers.payload(new StringSource("<ExampleResponse>42</ExampleResponse>")));
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.webservices.server.WebServiceServerTest
import org.springframework.ws.test.server.MockWebServiceClient
import org.springframework.ws.test.server.RequestCreators
import org.springframework.ws.test.server.ResponseMatchers
import org.springframework.xml.transform.StringSource

@WebServiceServerTest(ExampleEndpoint::class)
class MyWebServiceServerTests(@Autowired val client: MockWebServiceClient) {

    @Test
    fun mockServerCall() {
        client
            .sendRequest(RequestCreators.withPayload(StringSource("<ExampleRequest/>")))
            .andExpect(ResponseMatchers.payload(StringSource("<ExampleResponse>42</ExampleResponse>")))
    }

}

9.3.34. 追加の自動構成とスライス

各スライスは、スライスの一部として含まれるべき自動構成を定義する 1 つ以上の @AutoConfigure…​ アノテーションを提供します。次の例に示すように、カスタム @AutoConfigure…​ アノテーションを作成するか、@ImportAutoConfiguration をテストに追加することにより、テストごとに自動構成を追加できます。

Java
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration;
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest;

@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration.class)
class MyJdbcTests {

}
Kotlin
import org.springframework.boot.autoconfigure.ImportAutoConfiguration
import org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration
import org.springframework.boot.test.autoconfigure.jdbc.JdbcTest

@JdbcTest
@ImportAutoConfiguration(IntegrationAutoConfiguration::class)
class MyJdbcTests
自動構成は Spring Boot によって特定の方法で処理されるため、通常の @Import アノテーションを使用して自動構成をインポートしないようにしてください。

または、次の例に示すように、META-INF/spring に保存されているファイルにスライスアノテーションを登録することにより、スライスアノテーションを使用するための自動構成を追加できます。

META-INF/Spring/org.springframework.boot.test.autoconfigure.jdbc.JdbcTest.imports
com.example.IntegrationAutoConfiguration

この例では、@JdbcTest でアノテーションが付けられたすべてのテストで com.example.IntegrationAutoConfiguration が有効になっています。

このファイルでは、# でコメントを使用できます。
スライスまたは @AutoConfigure…​ アノテーションは、@ImportAutoConfiguration でメタアノテーションが付けられている限り、この方法でカスタマイズできます。

9.3.35. ユーザー設定とスライス

コードを適切な方法で構成する場合、@SpringBootApplication クラスはデフォルトでテストの構成として使用されます

その場合、アプリケーションのメインクラスに、その機能の特定の領域に固有の構成設定を散らかさないことが重要になります。

Spring Data MongoDB を使用しており、その自動構成に依存しており、監査を有効にしていると仮定します。@SpringBootApplication を次のように定義できます。

Java
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.config.EnableMongoAuditing;

@SpringBootApplication
@EnableMongoAuditing
public class MyApplication {

    // ...

}
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.data.mongodb.config.EnableMongoAuditing

@SpringBootApplication
@EnableMongoAuditing
class MyApplication {

    // ...

}

このクラスはテストのソース構成であるため、スライステストでは実際に Mongo 監査を有効にしようとしますが、これは明らかに意図したものではありません。推奨されるアプローチは、次の例に示すように、その領域固有の構成をアプリケーションと同じレベルの別の @Configuration クラスに移動することです。

Java
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.EnableMongoAuditing;

@Configuration(proxyBeanMethods = false)
@EnableMongoAuditing
public class MyMongoConfiguration {

    // ...

}
Kotlin
import org.springframework.context.annotation.Configuration
import org.springframework.data.mongodb.config.EnableMongoAuditing

@Configuration(proxyBeanMethods = false)
@EnableMongoAuditing
class MyMongoConfiguration {

    // ...

}
アプリケーションの複雑さに応じて、カスタマイズ用に 1 つの @Configuration クラスを使用することも、ドメイン領域ごとに 1 つのクラスを使用することもできます。後者のアプローチでは、必要に応じて、@Import アノテーションを使用してテストの 1 つでそれを有効にすることができます。スライステストで特定の @Configuration クラスを有効にする場合の詳細については、この使い方セクションを参照してください。

テストスライスは、@Configuration クラスをスキャンから除外します。例: @WebMvcTest の場合、次の構成では、テストスライスによってロードされたアプリケーションコンテキストに特定の WebMvcConfigurer Bean は含まれません。

Java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration(proxyBeanMethods = false)
public class MyWebConfiguration {

    @Bean
    public WebMvcConfigurer testConfigurer() {
        return new WebMvcConfigurer() {
            // ...
        };
    }

}
Kotlin
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer

@Configuration(proxyBeanMethods = false)
class MyWebConfiguration {

    @Bean
    fun testConfigurer(): WebMvcConfigurer {
        return object : WebMvcConfigurer {
            // ...
        }
    }

}

ただし、以下の構成では、テストスライスによってカスタム WebMvcConfigurer がロードされます。

Java
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Component
public class MyWebMvcConfigurer implements WebMvcConfigurer {

    // ...

}
Kotlin
import org.springframework.stereotype.Component
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer

@Component
class MyWebMvcConfigurer : WebMvcConfigurer {

    // ...

}

混乱のもう 1 つの原因は、クラスパススキャンです。実用的な方法でコードを構造化しながら、追加のパッケージをスキャンする必要があると仮定します。アプリケーションは次のコードのようになります。

Java
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan({ "com.example.app", "com.example.another" })
public class MyApplication {

    // ...

}
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.ComponentScan

@SpringBootApplication
@ComponentScan("com.example.app", "com.example.another")
class MyApplication {

    // ...

}

そうすることで、デフォルトのコンポーネントスキャンディレクティブが効果的にオーバーライドされ、選択したスライスに関係なく、これら 2 つのパッケージがスキャンされるという副作用があります。たとえば、@DataJpaTest は、アプリケーションのコンポーネントとユーザー構成を突然スキャンするようです。繰り返しますが、カスタムディレクティブを別のクラスに移動することは、この課題を解決するための良い方法です。

これが選択肢ではない場合は、テストの階層のどこかに @SpringBootConfiguration を作成して、代わりに使用することができます。あるいは、テストのソースを指定して、デフォルトのソースを見つける動作を無効にすることもできます。

9.3.36. Spock を使用して Spring Boot アプリケーションをテストする

Spock 2.2 以降は、Spring Boot アプリケーションのテストに使用できます。これを行うには、Spock の spock-spring モジュールの -groovy-4.0 バージョンへの依存関係をアプリケーションのビルドに追加します。spock-spring は、Spring のテストフレームワークを Spock に統合します。詳細については、Spock の Spring モジュールのドキュメント (英語) を参照してください。

9.4. Testcontainers

Testcontainers (英語) ライブラリは、Docker コンテナー内で実行されるサービスを管理する方法を提供します。JUnit と統合されているため、テストを実行する前にコンテナーを起動できるテストクラスを作成できます。Testcontainers は、MySQL、MongoDB、Cassandra などの実際のバックエンドサービスと通信する統合テストを作成する場合に特に役立ちます。

テストコンテナーは、Spring Boot テストで次のように使用できます。

Java
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import org.springframework.boot.test.context.SpringBootTest;

@Testcontainers
@SpringBootTest
class MyIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");

    @Test
    void myTest() {
        // ...
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.testcontainers.containers.Neo4jContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers

@Testcontainers
@SpringBootTest
class MyIntegrationTests {

    @Test
    fun myTest() {
        // ...
    }

    companion object {

        @Container
        val neo4j = Neo4jContainer("neo4j:5")

    }

}

これにより、テストが実行される前に、Neo4j を実行する docker コンテナーが起動されます (Docker がローカルで実行されている場合)。ほとんどの場合、コンテナーで実行されているサービスに接続するようにアプリケーションを構成する必要があります。

9.4.1. サービス接続

サービス接続は、任意の リモートサービスへの接続です。Spring Boot の自動構成は、サービス接続の詳細を消費し、使用して リモートサービスへの接続を確立できます。その場合、接続の詳細は、接続関連の構成プロパティよりも優先されます。

Testcontainers を使用すると、テストクラスのコンテナーフィールドにアノテーションを付けることで、コンテナーで実行されているサービスの接続の詳細を自動的に作成できます。

Java
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;

@Testcontainers
@SpringBootTest
class MyIntegrationTests {

    @Container
    @ServiceConnection
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");

    @Test
    void myTest() {
        // ...
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
import org.testcontainers.containers.Neo4jContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers

@Testcontainers
@SpringBootTest
class MyIntegrationTests {

    @Test
    fun myTest() {
        // ...
    }

    companion object {

        @Container
        @ServiceConnection
        val neo4j = Neo4jContainer("neo4j:5")

    }

}

@ServiceConnection のおかげで、上記の構成により、アプリケーション内の Neo4j 関連の Bean は、Testcontainers が管理する Docker コンテナー内で実行されている Neo4j と通信できます。これは、Neo4j 自動構成によって使用される Neo4jConnectionDetails Bean を自動的に定義し、接続関連の構成プロパティをオーバーライドすることによって行われます。

Testcontainers とのサービス接続を使用するには、spring-boot-testcontainers モジュールをテストの依存関係として追加する必要があります。

サービス接続アノテーションは、spring.factories に登録された ContainerConnectionDetailsFactory クラスによって処理されます。ContainerConnectionDetailsFactory は、特定の Container サブクラス、または Docker イメージ名に基づいて ConnectionDetails Bean を作成できます。

spring-boot-testcontainers jar では、次のサービス接続ファクトリが提供されます。

接続詳細 一致

ActiveMQConnectionDetails

"symptoma/activemq" という名前のコンテナー

CassandraConnectionDetails

CassandraContainer 型のコンテナー

CouchbaseConnectionDetails

CouchbaseContainer 型のコンテナー

ElasticsearchConnectionDetails

ElasticsearchContainer 型のコンテナー

FlywayConnectionDetails

JdbcDatabaseContainer 型のコンテナー

JdbcConnectionDetails

JdbcDatabaseContainer 型のコンテナー

KafkaConnectionDetails

org.testcontainers.containers.KafkaContainer または RedpandaContainer 型のコンテナー

LiquibaseConnectionDetails

JdbcDatabaseContainer 型のコンテナー

MongoConnectionDetails

MongoDBContainer 型のコンテナー

Neo4jConnectionDetails

Neo4jContainer 型のコンテナー

OtlpMetricsConnectionDetails

"otel/opentelemetry-collector-contrib" という名前のコンテナー

OtlpTracingConnectionDetails

"otel/opentelemetry-collector-contrib" という名前のコンテナー

PulsarConnectionDetails

PulsarContainer 型のコンテナー

R2dbcConnectionDetails

MariaDBContainerMSSQLServerContainerMySQLContainerOracleContainer または PostgreSQLContainer 型のコンテナー

RabbitConnectionDetails

RabbitMQContainer 型のコンテナー

RedisConnectionDetails

"redis" という名前のコンテナー

ZipkinConnectionDetails

"openzipkin/zipkin" という名前のコンテナー

デフォルトでは、該当するすべての接続詳細 Bean が特定の Container に対して作成されます。例: PostgreSQLContainer は JdbcConnectionDetails と R2dbcConnectionDetails の両方を作成します。

該当する型のサブセットのみを作成する場合は、@ServiceConnection の type 属性を使用できます。

デフォルトでは、接続の詳細を見つけるために使用される名前を取得するために Container.getDockerImageName().getRepository() が使用されます。Docker イメージ名のリポジトリ部分は、レジストリとバージョンを無視します。これは、Spring Boot が Container のインスタンスを取得できる限り機能します。これは、上記の例のように static フィールドを使用する場合に当てはまります。

@Bean メソッドを使用している場合、Spring Boot は Bean メソッドを呼び出して Docker イメージ名を取得しません。これは、早期初期化の問題が発生する可能性があるためです。代わりに、Bean メソッドの戻り値の型を使用して、どの接続詳細を使用する必要があるかを調べます。これは、型付きコンテナーを使用している限り機能します。Neo4jContainer または RabbitMQContainerGenericContainer を使用している場合、これは機能しなくなります。次の例に示すように、Redis を使用します。

Java
import org.testcontainers.containers.GenericContainer;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;

@TestConfiguration(proxyBeanMethods = false)
public class MyRedisConfiguration {

    @Bean
    @ServiceConnection(name = "redis")
    public GenericContainer<?> redisContainer() {
        return new GenericContainer<>("redis:7");
    }

}
Kotlin
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
import org.springframework.context.annotation.Bean
import org.testcontainers.containers.GenericContainer

@TestConfiguration(proxyBeanMethods = false)
class MyRedisConfiguration {

    @Bean
    @ServiceConnection(name = "redis")
    fun redisContainer(): GenericContainer<*> {
        return GenericContainer("redis:7")
    }

}

Spring Boot は、GenericContainer からどのコンテナーイメージが使用されているかを知ることができないため、そのヒントを提供するには @ServiceConnection の name 属性を使用する必要があります。

@ServiceConnection の name 属性を使用して、カスタムイメージを使用する場合などに、どの接続詳細が使用されるかをオーバーライドすることもできます。Docker イメージ registry.mycompany.com/mirror/myredis を使用している場合は、@ServiceConnection(name="redis") を使用して RedisConnectionDetails が確実に作成されるようにします。

9.4.2. 動的プロパティ

@DynamicPropertySource は、サービス接続に代わる、やや冗長ですが、より柔軟な代替手段です。静的 @DynamicPropertySource メソッドを使用すると、動的プロパティ値を Spring 環境に追加できます。

Java
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;

@Testcontainers
@SpringBootTest
class MyIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>("neo4j:5");

    @Test
    void myTest() {
        // ...
    }

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.Neo4jContainer
import org.testcontainers.junit.jupiter.Container
import org.testcontainers.junit.jupiter.Testcontainers

@Testcontainers
@SpringBootTest
class MyIntegrationTests {

    @Test
    fun myTest() {
        // ...
    }

    companion object {

        @Container
        val neo4j = Neo4jContainer("neo4j:5")

        @DynamicPropertySource
        fun neo4jProperties(registry: DynamicPropertyRegistry) {
            registry.add("spring.neo4j.uri") { neo4j.boltUrl }
        }

    }

}

上記の構成により、アプリケーション内の Neo4j 関連の Bean が、Testcontainers が管理する Docker コンテナー内で実行されている Neo4j と通信できるようになります。

9.5. テストユーティリティ

アプリケーションのテスト時に一般的に役立ついくつかのテストユーティリティクラスは、spring-boot の一部としてパッケージ化されています。

9.5.1. ConfigDataApplicationContextInitializer

ConfigDataApplicationContextInitializer は、Spring Boot application.properties ファイルをロードするテストに適用できる ApplicationContextInitializer です。次の例に示すように、@SpringBootTest が提供する機能の完全なセットが不要な場合に使用できます。

Java
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
import org.springframework.test.context.ContextConfiguration;

@ContextConfiguration(classes = Config.class, initializers = ConfigDataApplicationContextInitializer.class)
class MyConfigFileTests {

    // ...

}
Kotlin
import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer
import org.springframework.test.context.ContextConfiguration

@ContextConfiguration(classes = [Config::class], initializers = [ConfigDataApplicationContextInitializer::class])
class MyConfigFileTests {

    // ...

}
ConfigDataApplicationContextInitializer を単独で使用しても、@Value("${…​}") インジェクションはサポートされません。その唯一のジョブは、application.properties ファイルが Spring の Environment にロードされるようにすることです。@Value をサポートするには、PropertySourcesPlaceholderConfigurer を追加で構成するか、@SpringBootTest を使用して自動で構成する必要があります。

9.5.2. TestPropertyValues

TestPropertyValues を使用すると、ConfigurableEnvironment または ConfigurableApplicationContext にプロパティをすばやく追加できます。次のように、key=value 文字列で呼び出すことができます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.mock.env.MockEnvironment;

import static org.assertj.core.api.Assertions.assertThat;

class MyEnvironmentTests {

    @Test
    void testPropertySources() {
        MockEnvironment environment = new MockEnvironment();
        TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment);
        assertThat(environment.getProperty("name")).isEqualTo("Boot");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.boot.test.util.TestPropertyValues
import org.springframework.mock.env.MockEnvironment

class MyEnvironmentTests {

    @Test
    fun testPropertySources() {
        val environment = MockEnvironment()
        TestPropertyValues.of("org=Spring", "name=Boot").applyTo(environment)
        assertThat(environment.getProperty("name")).isEqualTo("Boot")
    }

}

9.5.3. OutputCapture

OutputCapture は、System.out および System.err 出力をキャプチャーするために使用できる JUnit Extension です。これを使用するには、次のように @ExtendWith(OutputCaptureExtension.class) を追加し、CapturedOutput を引数としてテストクラスコンストラクターまたはテストメソッドに挿入します。

Java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(OutputCaptureExtension.class)
class MyOutputCaptureTests {

    @Test
    void testName(CapturedOutput output) {
        System.out.println("Hello World!");
        assertThat(output).contains("World");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.system.CapturedOutput
import org.springframework.boot.test.system.OutputCaptureExtension

@ExtendWith(OutputCaptureExtension::class)
class MyOutputCaptureTests {

    @Test
    fun testName(output: CapturedOutput?) {
        println("Hello World!")
        assertThat(output).contains("World")
    }

}

9.5.4. TestRestTemplate

TestRestTemplate は、統合テストで役立つ Spring の RestTemplate の便利な代替手段です。バニラテンプレートまたは基本 HTTP 認証(ユーザー名とパスワードを使用)を送信するテンプレートを入手できます。いずれの場合も、テンプレートはフォールトトレラントです。これは、4xx および 5xx エラーで例外をスローしないことにより、テストに適した方法で動作することを意味します。代わりに、そのようなエラーは、返された ResponseEntity とそのステータスコードを介して検出できます。

Spring Framework 5.0 は、WebFlux 統合テストおよび WebFlux および MVC のエンドツーエンドテストの両方で機能する新しい WebTestClient を提供します。TestRestTemplate とは異なり、アサーションのための流れるような API を提供します。

Apache HTTP クライアント (バージョン 5.1 以降) の使用が推奨されますが、必須ではありません。クラスパスにこのクライアントがある場合、TestRestTemplate はクライアントを適切に構成して応答します。Apache の HTTP クライアントを使用する場合、テストに適したいくつかの追加機能が有効になります。

  • リダイレクトは追跡されません(したがって、レスポンスの場所をアサートできます)。

  • Cookie は無視されます(したがって、テンプレートはステートレスです)。

TestRestTemplate は、次の例に示すように、統合テストで直接インスタンス化できます。

Java
import org.junit.jupiter.api.Test;

import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;

import static org.assertj.core.api.Assertions.assertThat;

class MyTests {

    private final TestRestTemplate template = new TestRestTemplate();

    @Test
    void testRequest() {
        ResponseEntity<String> headers = this.template.getForEntity("https://myhost.example.com/example", String.class);
        assertThat(headers.getHeaders().getLocation()).hasHost("other.example.com");
    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.boot.test.web.client.TestRestTemplate

class MyTests {

    private val template = TestRestTemplate()

    @Test
    fun testRequest() {
        val headers = template.getForEntity("https://myhost.example.com/example", String::class.java)
        assertThat(headers.headers.location).hasHost("other.example.com")
    }

}

あるいは、WebEnvironment.RANDOM_PORT または WebEnvironment.DEFINED_PORT で @SpringBootTest アノテーションを使用する場合、完全に構成された TestRestTemplate を注入して使用を開始できます。必要に応じて、RestTemplateBuilder Bean を通じて追加のカスタマイズを適用できます。次の例に示すように、ホストとポートを指定しない URL はすべて、組み込みサーバーに自動的に接続します。

Java
import java.time.Duration;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests {

    @Autowired
    private TestRestTemplate template;

    @Test
    void testRequest() {
        HttpHeaders headers = this.template.getForEntity("/example", String.class).getHeaders();
        assertThat(headers.getLocation()).hasHost("other.example.com");
    }

    @TestConfiguration(proxyBeanMethods = false)
    static class RestTemplateBuilderConfiguration {

        @Bean
        RestTemplateBuilder restTemplateBuilder() {
            return new RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
                .setReadTimeout(Duration.ofSeconds(1));
        }

    }

}
Kotlin
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.test.web.client.TestRestTemplate
import org.springframework.boot.web.client.RestTemplateBuilder
import org.springframework.context.annotation.Bean
import java.time.Duration

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MySpringBootTests(@Autowired val template: TestRestTemplate) {

    @Test
    fun testRequest() {
        val headers = template.getForEntity("/example", String::class.java).headers
        assertThat(headers.location).hasHost("other.example.com")
    }

    @TestConfiguration(proxyBeanMethods = false)
    internal class RestTemplateBuilderConfiguration {

        @Bean
        fun restTemplateBuilder(): RestTemplateBuilder {
            return RestTemplateBuilder().setConnectTimeout(Duration.ofSeconds(1))
                .setReadTimeout(Duration.ofSeconds(1))
        }

    }

}

10. Docker Compose サポート

Docker Compose は、アプリケーションが必要とするサービスの複数のコンテナーを定義および管理するために使用できる一般的なテクノロジです。compose.yml ファイルは通常、サービスコンテナーを定義および構成するアプリケーションの隣に作成されます。

Docker Compose の一般的なワークフローは、docker compose up を実行し、開始されたサービスに接続してアプリケーションを操作し、完了したら docker compose down を実行します。

spring-boot-docker-compose モジュールをプロジェクトに含めると、Docker Compose を使用したコンテナーの操作のサポートを提供できます。次の Maven および Gradle のリストに示すように、モジュールの依存関係をビルドに追加します。

Maven
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-docker-compose</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
Gradle
dependencies {
    developmentOnly("org.springframework.boot:spring-boot-docker-compose")
}

このモジュールが依存関係として含まれている場合、Spring Boot は次のことを行います。

  • 作業ディレクトリで compose.yml やその他の一般的な compose ファイル名を検索します

  • 検出された compose.yml を使用して docker compose up を呼び出します

  • サポートされているコンテナーごとにサービス接続 Bean を作成する

  • アプリケーションのシャットダウン時に docker compose stop を呼び出します

アプリケーションの起動時に Docker Compose サービスがすでに実行されている場合、Spring Boot はサポートされているコンテナーごとにサービス接続 Bean のみを作成します。再び docker compose up を呼び出すことはなく、アプリケーションのシャットダウン時に docker compose stop を呼び出すこともありません。

再パッケージ化されたアーカイブには、デフォルトでは Spring Boot の Docker Compose が含まれていません。このサポートを使用する場合は、これを含める必要があります。Maven プラグインを使用する場合は、excludeDockerCompose プロパティを false に設定します。Gradle プラグインを使用する場合は、タスクのクラスパスを構成して developmentOnly 構成を含めます (英語)

10.1. 前提条件

パス上に docker および docker compose (または docker-compose) CLI アプリケーションが必要です。サポートされる Docker Compose の最小バージョンは 2.2.0 です。

10.2. サービス接続

サービス接続は、任意の リモートサービスへの接続です。Spring Boot の自動構成は、サービス接続の詳細を消費し、使用して リモートサービスへの接続を確立できます。その場合、接続の詳細は、接続関連の構成プロパティよりも優先されます。

Spring Boot の Docker Compose サポートを使用する場合、コンテナーによってマップされたポートへのサービス接続が確立されます。

Docker compose は通常、コンテナー内のポートがコンピューター上の一時ポートにマップされるような方法で使用されます。例: Postgres サーバーはポート 5432 を使用してコンテナー内で実行されますが、ローカルではまったく異なるポートにマッピングされます。サービス接続は常に、ローカルにマップされたポートを検出して使用します。

サービス接続は、コンテナーのイメージ名を使用して確立されます。現在、次のサービス接続がサポートされています。

接続詳細 一致

ActiveMQConnectionDetails

"symptoma/activemq" という名前のコンテナー

CassandraConnectionDetails

"cassandra" という名前のコンテナー

ElasticsearchConnectionDetails

"elasticsearch" という名前のコンテナー

JdbcConnectionDetails

"gvenzl/oracle-free"、"gvenzl/oracle-xe"、"mariadb"、"mssql/server"、"mysql"、"postgres" という名前のコンテナー

MongoConnectionDetails

"mongo" という名前のコンテナー

Neo4jConnectionDetails

"neo4j" という名前のコンテナー

OtlpMetricsConnectionDetails

"otel/opentelemetry-collector-contrib" という名前のコンテナー

OtlpTracingConnectionDetails

"otel/opentelemetry-collector-contrib" という名前のコンテナー

PulsarConnectionDetails

"apachepulsar/pulsar" という名前のコンテナー

R2dbcConnectionDetails

"gvenzl/oracle-free"、"gvenzl/oracle-xe"、"mariadb"、"mssql/server"、"mysql"、"postgres" という名前のコンテナー

RabbitConnectionDetails

"rabbitmq" という名前のコンテナー

RedisConnectionDetails

"redis" という名前のコンテナー

ZipkinConnectionDetails

"openzipkin/zipkin" という名前のコンテナー。

10.3. カスタム画像

サービスを提供するために、独自のバージョンのイメージを使用する必要がある場合があります。標準イメージと同じように動作する限り、任意のカスタムイメージを使用できます。具体的には、標準イメージがサポートする環境変数はカスタムイメージでも使用する必要があります。

イメージで別の名前が使用されている場合は、Spring Boot がサービス接続を提供できるように、compose.yml ファイルでラベルを使用できます。org.springframework.boot.service-connection という名前のラベルを使用してサービス名を指定します。

例:

services:
  redis:
    image: 'mycompany/mycustomredis:7.0'
    ports:
      - '6379'
    labels:
      org.springframework.boot.service-connection: redis

10.4. 特定のコンテナーをスキップする

compose.yml で定義されたコンテナーイメージがアプリケーションに接続したくない場合は、ラベルを使用してそれを無視できます。org.springframework.boot.ignore というラベルが付いたコンテナーは、Spring Boot によって無視されます。

例:

services:
  redis:
    image: 'redis:7.0'
    ports:
      - '6379'
    labels:
      org.springframework.boot.ignore: true

10.5. 特定の構成ファイルの使用

作成ファイルがアプリケーションと同じディレクトリにない場合、または別の名前が付けられている場合は、application.properties または application.yaml で spring.docker.compose.file を使用して別のファイルを指すことができます。プロパティは、正確なパスまたはアプリケーションに対する相対パスとして定義できます。

例:

Properties
spring.docker.compose.file=../my-compose.yml
Yaml
spring:
  docker:
    compose:
      file: "../my-compose.yml"

10.6. コンテナーの準備が完了するまで待機

Docker Compose によって開始されたコンテナーは、完全に準備が完了するまでに時間がかかる場合があります。準備が整っているかどうかを確認する推奨方法は、compose.yml ファイルのサービス定義に healthcheck セクションを追加することです。

healthcheck 構成が compose.yml ファイルから省略されることは珍しいことではないため、Spring Boot はサービスの準備状況を直接チェックします。デフォルトでは、マップされたポートへの TCP/IP 接続を確立できる場合、コンテナーは準備完了とみなされます。

compose.yml ファイルに org.springframework.boot.readiness-check.tcp.disable ラベルを追加することで、コンテナーごとにこれを無効にできます。

例:

services:
  redis:
    image: 'redis:7.0'
    ports:
      - '6379'
    labels:
      org.springframework.boot.readiness-check.tcp.disable: true

application.properties または application.yaml ファイルでタイムアウト値を変更することもできます。

Properties
spring.docker.compose.readiness.tcp.connect-timeout=10s
spring.docker.compose.readiness.tcp.read-timeout=5s
Yaml
spring:
  docker:
    compose:
      readiness:
        tcp:
          connect-timeout: 10s
          read-timeout: 5s

全体のタイムアウトは spring.docker.compose.readiness.timeout を使用して構成できます。

10.7. Docker Compose ライフサイクルの制御

デフォルトでは、Spring Boot はアプリケーションの起動時に docker compose up を呼び出し、シャットダウン時に docker compose stop を呼び出します。別のライフサイクル管理を使用したい場合は、spring.docker.compose.lifecycle-management プロパティを使用できます。

次の値がサポートされています。

  • none - Docker Compose を起動または停止しないでください

  • start-only - アプリケーションの起動時に Docker Compose を起動し、実行したままにします。

  • start-and-stop - アプリケーションの起動時に Docker Compose を起動し、JVM の終了時に停止します。

さらに、spring.docker.compose.start.command プロパティを使用して、docker compose up または docker compose start のどちらを使用するかを変更できます。spring.docker.compose.stop.command では、docker compose down または docker compose stop を使用するかどうかを設定できます。

次の例は、ライフサイクル管理を構成する方法を示しています。

Properties
spring.docker.compose.lifecycle-management=start-and-stop
spring.docker.compose.start.command=start
spring.docker.compose.stop.command=down
spring.docker.compose.stop.timeout=1m
Yaml
spring:
  docker:
    compose:
      lifecycle-management: start-and-stop
      start:
        command: start
      stop:
        command: down
        timeout: 1m

10.8. Docker Compose プロファイルのアクティブ化

Docker Compose プロファイルは、特定の環境に合わせて Docker Compose 構成を調整できるという点で Spring プロファイルに似ています。特定の Docker Compose プロファイルをアクティブ化する場合は、application.properties または application.yaml ファイルで spring.docker.compose.profiles.active プロパティを使用できます。

Properties
spring.docker.compose.profiles.active=myprofile
Yaml
spring:
  docker:
    compose:
      profiles:
        active: "myprofile"

10.9. テストでの Docker Compose の使用

デフォルトでは、テストの実行時に Spring Boot の Docker Compose サポートは無効になっています。

テストで Docker Compose サポートを有効にするには、spring.docker.compose.skip.in-tests を false に設定します。

Gradle を使用する場合は、spring-boot-docker-compose 依存関係の構成を developmentOnly から testAndDevelopmentOnly に変更する必要もあります。

Gradle
dependencies {
    testAndDevelopmentOnly("org.springframework.boot:spring-boot-docker-compose")
}

11. テストコンテナーのサポート

Testcontainers を統合テストに使用するだけでなく、開発時に使用することもできます。次のセクションでは、これについて詳しく説明します。

11.1. 開発時のテストコンテナーの使用

このアプローチにより、開発者はアプリケーションが依存するサービスのコンテナーを迅速に起動できるため、データベースサーバーなどを手動でプロビジョニングする必要がなくなります。この方法で Testcontainers を使用すると、コンテナー構成が YAML ではなく Java であることを除いて、Docker Compose と同様の機能が提供されます。

開発時に Testcontainer を使用するには、"main" クラスパスではなく "test" クラスパスを使用してアプリケーションを起動する必要があります。これにより、宣言されたすべてのテスト依存関係にアクセスできるようになり、テスト構成を自然に記述できる場所が提供されます。

アプリケーションのテスト起動可能なバージョンを作成するには、src/test ディレクトリに "Application" クラスを作成する必要があります。例: メインアプリケーションが src/main/java/com/example/MyApplication.java にある場合は、src/test/java/com/example/TestMyApplication.java を作成する必要があります

TestMyApplication クラスは、SpringApplication.from(…​) メソッドを使用して実際のアプリケーションを起動できます。

Java
import org.springframework.boot.SpringApplication;

public class TestMyApplication {

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

}
Kotlin
import org.springframework.boot.fromApplication

fun main(args: Array<String>) {
    fromApplication<MyApplication>().run(*args)
}

アプリケーションと一緒に開始する Container インスタンスも定義する必要があります。これを行うには、spring-boot-testcontainers モジュールが test 依存関係として追加されていることを確認する必要があります。それが完了したら、開始するコンテナーの @Bean メソッドを宣言する @TestConfiguration クラスを作成できます。

ConnectionDetails Bean を作成するために、@Bean メソッドに @ServiceConnection アノテーションを付けることもできます。サポートされているテクノロジーの詳細については、「サービス接続」セクションを参照してください。

典型的な Testcontainers 構成は次のようになります。

Java
import org.testcontainers.containers.Neo4jContainer;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;

@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {

    @Bean
    @ServiceConnection
    public Neo4jContainer<?> neo4jContainer() {
        return new Neo4jContainer<>("neo4j:5");
    }

}
Kotlin
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
import org.springframework.context.annotation.Bean
import org.testcontainers.containers.Neo4jContainer

@TestConfiguration(proxyBeanMethods = false)
class MyContainersConfiguration {

    @Bean
    @ServiceConnection
    fun neo4jContainer(): Neo4jContainer<*> {
        return Neo4jContainer("neo4j:5")
    }

}
Container Bean のライフサイクルは、Spring Boot によって自動的に管理されます。コンテナーは自動的に起動および停止されます。
spring.testcontainers.beans.startup プロパティを使用して、コンテナーの起動方法を変更できます。デフォルトでは sequential 起動が使用されますが、複数のコンテナーを並行して起動する場合は、parallel を選択することもできます。

テスト構成を定義したら、with(…​) メソッドを使用してテストランチャーに接続できます。

Java
import org.springframework.boot.SpringApplication;

public class TestMyApplication {

    public static void main(String[] args) {
        SpringApplication.from(MyApplication::main).with(MyContainersConfiguration.class).run(args);
    }

}
Kotlin
import org.springframework.boot.fromApplication
import org.springframework.boot.with

fun main(args: Array<String>) {
    fromApplication<MyApplication>().with(MyContainersConfiguration::class).run(*args)
}

これで、通常の Java main メソッドアプリケーションと同じように TestMyApplication を起動して、アプリケーションと実行する必要のあるコンテナーを開始できるようになりました。

Maven ゴール spring-boot:test-run または Gradle タスク bootTestRun を使用して、コマンドラインからこれを行うことができます。

11.1.1. 開発時に動的プロパティを提供する

開発時に Container @Bean メソッドから動的プロパティを提供したい場合は、DynamicPropertyRegistry を注入することで実行できます。これは、テストで使用できる @DynamicPropertySource アノテーションと同様の方法で機能します。これにより、コンテナーの起動後に使用可能になるプロパティを追加できます。

一般的な構成は次のようになります。

Java
import org.testcontainers.containers.MongoDBContainer;

import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.DynamicPropertyRegistry;

@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {

    @Bean
    public MongoDBContainer mongoDbContainer(DynamicPropertyRegistry properties) {
        MongoDBContainer container = new MongoDBContainer("mongo:5.0");
        properties.add("spring.data.mongodb.host", container::getHost);
        properties.add("spring.data.mongodb.port", container::getFirstMappedPort);
        return container;
    }

}
Kotlin
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.test.context.DynamicPropertyRegistry
import org.testcontainers.containers.MongoDBContainer

@TestConfiguration(proxyBeanMethods = false)
class MyContainersConfiguration {

    @Bean
    fun monogDbContainer(properties: DynamicPropertyRegistry): MongoDBContainer {
        var container = MongoDBContainer("mongo:5.0")
        properties.add("spring.data.mongodb.host", container::getHost)
        properties.add("spring.data.mongodb.port", container::getFirstMappedPort)
        return container
    }

}
可能な限り @ServiceConnection を使用することをお勧めしますが、動的プロパティは、まだ @ServiceConnection をサポートしていないテクノロジにとって有用なフォールバックになる可能性があります。

11.1.2. Testcontainer 宣言クラスのインポート

Testcontainers を使用する場合の一般的なパターンは、Container インスタンスを静的フィールドとして宣言することです。多くの場合、これらのフィールドはテストクラスで直接定義されます。親クラスまたはテストが実装するインターフェース上で宣言することもできます。

例: 次の MyContainers インターフェースは、mongo コンテナーと neo4j コンテナーを宣言します。

import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.containers.Neo4jContainer;
import org.testcontainers.junit.jupiter.Container;

import org.springframework.boot.testcontainers.service.connection.ServiceConnection;

public interface MyContainers {

    @Container
    @ServiceConnection
    MongoDBContainer mongoContainer = new MongoDBContainer("mongo:5.0");

    @Container
    @ServiceConnection
    Neo4jContainer<?> neo4jContainer = new Neo4jContainer<>("neo4j:5");

}

すでにこの方法でコンテナーを定義している場合、またはこのスタイルを好む場合は、コンテナーを @Bean メソッドとして定義するのではなく、これらの宣言クラスをインポートできます。これを行うには、テスト構成クラスに @ImportTestcontainers アノテーションを追加します。

Java
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;

@TestConfiguration(proxyBeanMethods = false)
@ImportTestcontainers(MyContainers.class)
public class MyContainersConfiguration {

}
Kotlin
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.context.ImportTestcontainers

@TestConfiguration(proxyBeanMethods = false)
@ImportTestcontainers(MyContainers::class)
class MyContainersConfiguration
サービス接続機能を使用するつもりはなく、代わりに @DynamicPropertySource を使用したい場合は、Container フィールドから @ServiceConnection アノテーションを削除します。@DynamicPropertySource アノテーション付きメソッドを宣言クラスに追加することもできます。

11.1.3. 開発時にテストコンテナーで DevTools を使用する

devtools を使用する場合、Bean および Bean メソッドに @RestartScope のアノテーションを付けることができます。このような Bean は、devtools がアプリケーションを再起動するときに再作成されません。これは、アプリケーションの再起動にもかかわらず状態が維持されるため、Testcontainer Container Bean の場合に特に便利です。

Java
import org.testcontainers.containers.MongoDBContainer;

import org.springframework.boot.devtools.restart.RestartScope;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.context.annotation.Bean;

@TestConfiguration(proxyBeanMethods = false)
public class MyContainersConfiguration {

    @Bean
    @RestartScope
    @ServiceConnection
    public MongoDBContainer mongoDbContainer() {
        return new MongoDBContainer("mongo:5.0");
    }

}
Kotlin
import org.springframework.boot.devtools.restart.RestartScope
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.boot.testcontainers.service.connection.ServiceConnection
import org.springframework.context.annotation.Bean
import org.testcontainers.containers.MongoDBContainer

@TestConfiguration(proxyBeanMethods = false)
class MyContainersConfiguration {

    @Bean
    @RestartScope
    @ServiceConnection
    fun monogDbContainer(): MongoDBContainer {
        return MongoDBContainer("mongo:5.0")
    }

}
Gradle を使用していてこの機能を使用したい場合は、spring-boot-devtools 依存関係の構成を developmentOnly から testAndDevelopmentOnly に変更する必要があります。デフォルトのスコープ developmentOnly では、devtools がアクティブではないため、bootTestRun タスクはコード内の変更を取得しません。

12. 独自の自動構成の作成

共有ライブラリを開発している会社で働いている場合、またはオープンソースまたは有償ライブラリに取り組んでいる場合は、独自の自動構成を開発することをお勧めします。自動構成クラスは、外部 jar にバンドルすることができ、Spring Boot によって引き続き取得されます。

自動構成は、自動構成コードと、使用する一般的なライブラリを提供する「スターター」に関連付けることができます。最初に、独自の自動構成を構築するために知っておく必要があることを説明し、次にカスタムスターターの作成に必要な一般的な手順に進みます

12.1. 自動構成された Bean について

自動構成を実装するクラスには、@AutoConfiguration のアノテーションが付けられます。このアノテーション自体は @Configuration でメタアノテーションが付けられ、自動構成を標準の @Configuration クラスにします。追加の @Conditional アノテーションは、自動構成がいつ適用されるかを制約するために使用されます。通常、自動構成クラスは @ConditionalOnClass および @ConditionalOnMissingBean アノテーションを使用します。これにより、関連するクラスが見つかった場合、独自の @Configuration を宣言していない場合にのみ、自動構成が適用されます。

spring-boot-autoconfigure [GitHub] (英語) のソースコードを参照して、Spring が提供する @AutoConfiguration クラスを確認できます(META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports [GitHub] (英語) ファイルを参照)。

12.2. 自動構成候補の特定

Spring Boot は、公開された jar 内に META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports ファイルが存在するかどうかをチェックします。ファイルには、次の例に示すように、構成クラスが 1 行に 1 つのクラス名でリストされている必要があります。

com.mycorp.libx.autoconfigure.LibXAutoConfiguration
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
# 文字を使用して、インポートファイルにコメントを追加できます。
自動構成は、インポートファイルで指定することによってのみロードする必要があります。それらが特定のパッケージスペースで定義されていること、およびコンポーネントスキャンの対象にならないことを確認してください。さらに、自動構成クラスは、コンポーネントスキャンが追加のコンポーネントを検出できるようにすべきではありません。代わりに、特定の @Import アノテーションを使用する必要があります。

構成を特定の順序で適用する必要がある場合は、@AutoConfiguration [GitHub] (英語) アノテーションまたは専用の @AutoConfigureBefore [GitHub] (英語) および @AutoConfigureAfter [GitHub] (英語) アノテーションで beforebeforeNameafterafterName 属性を使用できます。例: Web 固有の構成を提供する場合、クラスを WebMvcAutoConfiguration の後に適用する必要がある場合があります。

相互の直接的な知識がないはずの特定の自動構成を並べ替える場合は、@AutoConfigureOrder も使用できます。そのアノテーションは、通常の @Order アノテーションと同じセマンティックを持ちますが、自動構成クラスに専用の順序を提供します。

標準の @Configuration クラスと同様に、自動構成クラスが適用される順序は、それらの Bean が定義される順序にのみ影響します。これらの Bean が後で作成される順序は影響を受けず、各 Bean の依存関連と @DependsOn 関連によって決定されます。

12.3. 条件アノテーション

ほとんどの場合、1 つ以上の @Conditional アノテーションを自動構成クラスに含める必要があります。@ConditionalOnMissingBean アノテーションは、デフォルトに満足できない場合に開発者が自動構成をオーバーライドできるようにするために使用される一般的な例の 1 つです。

Spring Boot には、@Configuration クラスまたは個々の @Bean メソッドにアノテーションを付けることにより、独自のコードで再利用できる多数の @Conditional アノテーションが含まれています。これらのアノテーションは次のとおりです。

12.3.1. クラス条件

@ConditionalOnClass および @ConditionalOnMissingClass アノテーションにより、特定のクラスの有無に基づいて @Configuration クラスを含めることができます。アノテーションメタデータは ASM (英語) を使用して解析されるという事実により、value 属性を使用して、実際のクラスを参照できます。ただし、そのクラスは実行中のアプリケーションクラスパスに実際には表示されない場合があります。String 値を使用してクラス名を指定する場合は、name 属性も使用できます。

このメカニズムは、通常戻り型が条件のターゲットである @Bean メソッドに同じ方法を適用しません。メソッドの条件が適用される前に、JVM はクラスをロードし、クラスが処理されると失敗する可能性のあるメソッド参照を処理します。現在ではない。

このシナリオを処理するには、次の例に示すように、別個の @Configuration クラスを使用して条件を分離できます。

Java
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@AutoConfiguration
// Some conditions ...
public class MyAutoConfiguration {

    // Auto-configured beans ...

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(SomeService.class)
    public static class SomeServiceConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public SomeService someService() {
            return new SomeService();
        }

    }

}
Kotlin
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
// Some conditions ...
class MyAutoConfiguration {

    // Auto-configured beans ...
    @Configuration(proxyBeanMethods = false)
    @ConditionalOnClass(SomeService::class)
    class SomeServiceConfiguration {

        @Bean
        @ConditionalOnMissingBean
        fun someService(): SomeService {
            return SomeService()
        }

    }

}
メタアノテーションの一部として @ConditionalOnClass または @ConditionalOnMissingClass を使用して独自の合成アノテーションを作成する場合、そのような場合はクラスを参照しないため、name を使用する必要があります。

12.3.2. Bean 条件

@ConditionalOnBean および @ConditionalOnMissingBean アノテーションにより、特定の Bean の有無に基づいて Bean を含めることができます。value 属性を使用して、型ごとに Bean を指定したり、name を使用して名前ごとに Bean を指定したりできます。search 属性を使用すると、Bean を検索するときに考慮する必要がある ApplicationContext 階層を制限できます。

@Bean メソッドに配置すると、次の例に示すように、ターゲット型はデフォルトでメソッドの戻り値型になります。

Java
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

@AutoConfiguration
public class MyAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public SomeService someService() {
        return new SomeService();
    }

}
Kotlin
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration(proxyBeanMethods = false)
class MyAutoConfiguration {

    @Bean
    @ConditionalOnMissingBean
    fun someService(): SomeService {
        return SomeService()
    }

}

上記の例では、SomeService 型の Bean が ApplicationContext に含まれていない場合、someService Bean が作成されます。

これらの条件はこれまでに処理されたものに基づいて評価されるため、Bean 定義が追加される順序には十分注意する必要があります。このため、自動構成クラスでは @ConditionalOnBean および @ConditionalOnMissingBean アノテーションのみを使用することをお勧めします(これらはユーザー定義の Bean 定義が追加された後にロードされることが保証されているため)。
@ConditionalOnBean および @ConditionalOnMissingBean は、@Configuration クラスの作成を妨げません。クラスレベルでこれらの条件を使用することと、含まれる各 @Bean メソッドをアノテーションでマークすることの唯一の違いは、条件が一致しない場合、前者は @Configuration クラスを Bean として登録できないことです。
@Bean メソッドを宣言するときは、メソッドの戻り型でできるだけ多くの型情報を提供してください。例: Bean の具象クラスがインターフェースを実装している場合、Bean メソッドの戻り型は、インターフェースではなく具象クラスである必要があります。@Bean メソッドで可能な限り多くの型情報を提供することは、Bean 条件を使用する場合に特に重要です。これは、Bean 条件の評価が、メソッドシグネチャーで使用可能な型情報にのみ依存するためです。

12.3.3. プロパティ条件

@ConditionalOnProperty アノテーションにより、Spring 環境プロパティに基づいて構成を含めることができます。prefix および name 属性を使用して、チェックするプロパティを指定します。デフォルトでは、存在し、false と等しくないプロパティはすべて一致します。havingValue および matchIfMissing 属性を使用して、より高度なチェックを作成することもできます。

name 属性に複数の名前が指定されている場合、条件が一致するにはすべてのプロパティがテストに合格する必要があります。

12.3.4. リソース条件

@ConditionalOnResource アノテーションを使用すると、特定のリソースが存在する場合にのみ構成を含めることができます。次の例に示すように、リソースは通常の Spring 規則を使用して指定できます: file:/home/user/test.dat

12.3.5. Web アプリケーション条件

@ConditionalOnWebApplication および @ConditionalOnNotWebApplication アノテーションを使用すると、アプリケーションが Web アプリケーションかどうかに応じて構成を含めることができます。サーブレットベースの Web アプリケーションは、Spring WebApplicationContext を使用するアプリケーション、session スコープを定義するアプリケーション、または ConfigurableWebEnvironment を持つアプリケーションです。リアクティブ Web アプリケーションは、ReactiveWebApplicationContext を使用する、または ConfigurableReactiveWebEnvironment を持つアプリケーションです。

@ConditionalOnWarDeployment および @ConditionalOnNotWarDeployment アノテーションを使用すると、アプリケーションがサーブレットコンテナーにデプロイされる従来の WAR アプリケーションであるかどうかに応じて、構成を含めることができます。この条件は、組み込み Web サーバーで実行されるアプリケーションには一致しません。

12.3.6. SpEL 式の条件

@ConditionalOnExpression アノテーションにより、SpEL 式の結果に基づいて構成を含めることができます。

式で Bean を参照すると、コンテキストリフレッシュ処理の非常に早い段階で Bean が初期化されます。その結果、Bean は後処理(構成プロパティのバインドなど)の対象にならず、その状態が不完全になる可能性があります。

12.4. 自動構成のテスト

自動構成は、ユーザー構成(@Bean 定義および Environment カスタマイズ)、条件評価(特定のライブラリの存在)など、多くの要因の影響を受ける可能性があります。具体的には、各テストで、これらのカスタマイズの組み合わせを表す、明確に定義された ApplicationContext を作成する必要があります。ApplicationContextRunner はそれを達成するための素晴らしい方法を提供します。

ApplicationContextRunner は、ネイティブイメージでテストを実行する場合には機能しません。

ApplicationContextRunner は通常、基本の共通構成を収集するためのテストクラスのフィールドとして定義されます。次の例では、MyServiceAutoConfiguration が常に呼び出されるようにします。

Java
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
    .withConfiguration(AutoConfigurations.of(MyServiceAutoConfiguration.class));
Kotlin
val contextRunner = ApplicationContextRunner()
    .withConfiguration(AutoConfigurations.of(MyServiceAutoConfiguration::class.java))
複数の自動構成を定義する必要がある場合、宣言はアプリケーションの実行時とまったく同じ順序で呼び出されるため、宣言を順序付ける必要はありません。

各テストでは、ランナーを使用して特定のユースケースを表すことができます。たとえば、次のサンプルはユーザー構成(UserConfiguration)を呼び出し、自動構成が適切にバックオフすることを確認します。run を呼び出すと、AssertJ で使用できるコールバックコンテキストが提供されます。

Java
@Test
void defaultServiceBacksOff() {
    this.contextRunner.withUserConfiguration(UserConfiguration.class).run((context) -> {
        assertThat(context).hasSingleBean(MyService.class);
        assertThat(context).getBean("myCustomService").isSameAs(context.getBean(MyService.class));
    });
}

@Configuration(proxyBeanMethods = false)
static class UserConfiguration {

    @Bean
    MyService myCustomService() {
        return new MyService("mine");
    }

}
Kotlin
@Test
fun defaultServiceBacksOff() {
    contextRunner.withUserConfiguration(UserConfiguration::class.java)
        .run { context: AssertableApplicationContext ->
            assertThat(context).hasSingleBean(MyService::class.java)
            assertThat(context).getBean("myCustomService")
                .isSameAs(context.getBean(MyService::class.java))
        }
}

@Configuration(proxyBeanMethods = false)
internal class UserConfiguration {

    @Bean
    fun myCustomService(): MyService {
        return MyService("mine")
    }

}

次の例に示すように、Environment を簡単にカスタマイズすることもできます。

Java
@Test
void serviceNameCanBeConfigured() {
    this.contextRunner.withPropertyValues("user.name=test123").run((context) -> {
        assertThat(context).hasSingleBean(MyService.class);
        assertThat(context.getBean(MyService.class).getName()).isEqualTo("test123");
    });
}
Kotlin
@Test
fun serviceNameCanBeConfigured() {
    contextRunner.withPropertyValues("user.name=test123").run { context: AssertableApplicationContext ->
        assertThat(context).hasSingleBean(MyService::class.java)
        assertThat(context.getBean(MyService::class.java).name).isEqualTo("test123")
    }
}

ランナーを使用して ConditionEvaluationReport を表示することもできます。レポートは、INFO または DEBUG レベルで出力できます。次の例は、ConditionEvaluationReportLoggingListener を使用して自動構成テストでレポートを出力する方法を示しています。

Java
import org.junit.jupiter.api.Test;

import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener;
import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;

class MyConditionEvaluationReportingTests {

    @Test
    void autoConfigTest() {
        new ApplicationContextRunner()
            .withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO))
            .run((context) -> {
                // Test something...
            });
    }

}
Kotlin
import org.junit.jupiter.api.Test
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
import org.springframework.boot.logging.LogLevel
import org.springframework.boot.test.context.assertj.AssertableApplicationContext
import org.springframework.boot.test.context.runner.ApplicationContextRunner

class MyConditionEvaluationReportingTests {

    @Test
    fun autoConfigTest() {
        ApplicationContextRunner()
            .withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO))
            .run { context: AssertableApplicationContext? -> }
    }

}

12.4.1. Web コンテキストのシミュレーション

サーブレットまたはリアクティブ Web アプリケーションのコンテキストでのみ動作する自動構成をテストする必要がある場合は、それぞれ WebApplicationContextRunner または ReactiveWebApplicationContextRunner を使用してください。

12.4.2. クラスパスのオーバーライド

実行時に特定のクラスやパッケージが存在しない場合に何が起こるかをテストすることもできます。Spring Boot には、ランナーが簡単に使用できる FilteredClassLoader が付属しています。次の例では、MyService が存在しない場合、自動構成が適切に無効になっていると断言します。

Java
@Test
void serviceIsIgnoredIfLibraryIsNotPresent() {
    this.contextRunner.withClassLoader(new FilteredClassLoader(MyService.class))
        .run((context) -> assertThat(context).doesNotHaveBean("myService"));
}
Kotlin
@Test
fun serviceIsIgnoredIfLibraryIsNotPresent() {
    contextRunner.withClassLoader(FilteredClassLoader(MyService::class.java))
        .run { context: AssertableApplicationContext? ->
            assertThat(context).doesNotHaveBean("myService")
        }
}

12.5. 独自のスターターを作成する

典型的な Spring Boot スターターには、特定のテクノロジーのインフラストラクチャを自動構成してカスタマイズするコードが含まれています。これを "acme" と呼びましょう。簡単に拡張できるようにするために、専用の名前空間にある多数の構成キーを環境に公開できます。最後に、ユーザーができるだけ簡単に開始できるように、単一の「スターター」依存関係が提供されています。

具体的には、カスタムスターターには次のものを含めることができます。

  • "acme" の自動構成コードを含む autoconfigure モジュール。

  • autoconfigure モジュールへの依存関係を提供する starter モジュール、および "acme" と通常役立つその他の依存関係。簡単に言えば、スターターを追加すると、そのライブラリの使用を開始するために必要なすべてが提供されます。

この 2 つのモジュールへの分離は、決して必要ではありません。"acme" にいくつかのフレーバー、オプション、オプション機能がある場合は、一部の機能がオプションであるという事実を明確に表現できるため、自動構成を分離することをお勧めします。さらに、これらのオプションの依存関係について意見を提供するスターターを作成することができます。同時に、他の人は autoconfigure モジュールのみに依存し、異なる意見で独自のスターターを作成することができます。

自動構成が比較的簡単で、オプション機能がない場合、スターターで 2 つのモジュールをマージすることは間違いなくオプションです。

12.5.1. ネーミング

スターターに適切な名前空間を提供するようにしてください。別の Maven groupId を使用している場合でも、モジュール名を spring-boot で始めないでください。将来的に自動構成するものについては、公式サポートを提供する場合があります。

経験則として、組み合わせたモジュールにはスターターにちなんで名前を付ける必要があります。例: "acme" のスターターを作成し、自動構成モジュールに acme-spring-boot およびスターター acme-spring-boot-starter の名前を付けると仮定します。2 つを結合するモジュールが 1 つしかない場合は、acme-spring-boot-starter という名前を付けます。

12.5.2. 構成キー

スターターが構成キーを提供する場合は、それらに一意の名前空間を使用します。特に、Spring Boot が使用する名前空間(servermanagementspring など)にキーを含めないでください。同じ名前空間を使用している場合、将来、モジュールを壊すような方法でこれらの名前空間を変更する可能性があります。経験則として、すべてのキーの前に、所有している名前空間(acme など)を付けます。

次の例に示すように、プロパティごとにフィールド javadoc を追加して、構成キーがドキュメント化されていることを確認します。

Java
import java.time.Duration;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties("acme")
public class AcmeProperties {

    /**
     * Whether to check the location of acme resources.
     */
    private boolean checkLocation = true;

    /**
     * Timeout for establishing a connection to the acme server.
     */
    private Duration loginTimeout = Duration.ofSeconds(3);

    // getters/setters ...

    public boolean isCheckLocation() {
        return this.checkLocation;
    }

    public void setCheckLocation(boolean checkLocation) {
        this.checkLocation = checkLocation;
    }

    public Duration getLoginTimeout() {
        return this.loginTimeout;
    }

    public void setLoginTimeout(Duration loginTimeout) {
        this.loginTimeout = loginTimeout;
    }

}
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties
import java.time.Duration

@ConfigurationProperties("acme")
class AcmeProperties(

    /**
     * Whether to check the location of acme resources.
     */
    var isCheckLocation: Boolean = true,

    /**
     * Timeout for establishing a connection to the acme server.
     */
    var loginTimeout:Duration = Duration.ofSeconds(3))
それらは JSON に追加される前に処理されないため、@ConfigurationProperties フィールドの Javadoc でプレーンテキストのみを使用する必要があります。

説明が一貫していることを確認するために、内部で従ういくつかのルールを次に示します。

  • "The" または "A" で説明を始めないでください。

  • boolean 型の場合、説明を "Whether" または "Enable" で開始します。

  • コレクションベースの型の場合、説明を「カンマ区切りリスト」で開始します

  • long ではなく java.time.Duration を使用し、「期間サフィックスが指定されていない場合は秒が使用されます」など、ミリ秒と異なる場合はデフォルトの単位を記述します。

  • 実行時に決定する必要がない限り、説明にデフォルト値を指定しないでください。

メタデータ生成をトリガーして、キーでも IDE 支援が利用できるようにしてください。生成されたメタデータ(META-INF/spring-configuration-metadata.json)を確認して、キーが適切にドキュメント化されていることを確認してください。互換性のある IDE で独自のスターターを使用することも、メタデータの品質を検証するための良いアイデアです。

12.5.3. 「自動構成」モジュール

autoconfigure モジュールには、ライブラリの使用を開始するために必要なすべてのものが含まれています。また、構成キーの定義(@ConfigurationProperties など)と、コンポーネントの初期化方法をさらにカスタマイズするために使用できるコールバックインターフェースも含まれている場合があります。

ライブラリへの依存関係をオプションとしてマークして、autoconfigure モジュールをプロジェクトに簡単に含めることができるようにする必要があります。そのようにすると、ライブラリは提供されず、デフォルトで Spring Boot はオフに戻ります。

Spring Boot は、アノテーションプロセッサーを使用して、自動構成の条件をメタデータファイル (META-INF/spring-autoconfigure-metadata.properties) に収集します。そのファイルが存在する場合は、一致しない自動構成を先行してフィルタリングするために使用され、起動時間が改善されます。

Maven でビルドする場合、自動構成を含むモジュールに次の依存関係を追加することをお勧めします。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure-processor</artifactId>
    <optional>true</optional>
</dependency>

アプリケーションで自動構成を直接定義した場合は、repackage ゴールが依存関係を uber jar に追加しないように、必ず spring-boot-maven-plugin を構成してください。

<project>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.springframework.boot</groupId>
                            <artifactId>spring-boot-autoconfigure-processor</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

次の例に示すように、Gradle では、依存関係を annotationProcessor 構成で宣言する必要があります。

dependencies {
    annotationProcessor "org.springframework.boot:spring-boot-autoconfigure-processor"
}

12.5.4. スターターモジュール

スターターは本当に空の jar です。その唯一の目的は、ライブラリを操作するために必要な依存関係を提供することです。それは、始めるために何が必要であるかについての意見に基づく見解と考えることができます。

スターターが追加されるプロジェクトについて想定しないでください。通常、自動構成するライブラリに他のスターターが必要な場合は、それらにもメンションしてください。オプションの依存関係の数が多い場合、ライブラリの通常の使用には不要な依存関係を含めることを避ける必要があるため、適切なデフォルトの依存関係のセットを提供するのは難しい場合があります。つまり、オプションの依存関係を含めないでください。

いずれの場合も、スターターはコア Spring Boot スターター(spring-boot-starter)を直接または間接的に参照する必要があります(スターターが別のスターターに依存している場合は、追加する必要はありません)。カスタムスターターのみを使用してプロジェクトを作成する場合、Spring Boot のコア機能は、コアスターターの存在によって尊重されます。

13. Kotlin サポート

Kotlin (英語) は、JVM(および他のプラットフォーム)を対象とする静的に型付けされた言語で、Java で記述された既存のライブラリとの相互運用性 (英語) を提供しながら、簡潔でエレガントなコードを記述できます。

Spring Boot は、Spring Framework、Spring Data、Reactor などの他の Spring プロジェクトのサポートを活用することにより、Kotlin サポートを提供します。詳細については、Spring Framework Kotlin サポートドキュメントを参照してください。

Spring Boot および Kotlin を開始する最も簡単な方法は、この包括的なチュートリアルに従うことです。start.spring.io を使用して、新しい Kotlin プロジェクトを作成できます。サポートが必要な場合は、Kotlin Slack (英語) の #spring チャネルに参加するか、Stack Overflow (英語) の spring タグと kotlin タグを使用して質問してください。

13.1. 要件

Spring Boot には少なくとも Kotlin 1.7.x が必要であり、依存関係管理を通じて適切な Kotlin バージョンを管理します。Kotlin を使用するには、org.jetbrains.kotlin:kotlin-stdlib と org.jetbrains.kotlin:kotlin-reflect がクラスパスに存在している必要があります。kotlin-stdlib バリアント kotlin-stdlib-jdk7 および kotlin-stdlib-jdk8 も使用できます。

Kotlin クラスはデフォルトで final (英語) 以降、プロキシできるように Spring アノテーション付きクラスを自動的に開くために、kotlin-spring (英語) プラグインを構成することをお勧めします。

Jackson の Kotlin モジュール [GitHub] (英語) は、Kotlin で JSON データをシリアライズ / デシリアライズするために必要です。クラスパスで見つかると自動的に登録されます。Jackson および Kotlin が存在するが、Jackson Kotlin モジュールが存在しない場合、警告メッセージがログに記録されます。

これらの依存関係とプラグインは、start.spring.io で Kotlin プロジェクトをブートストラップする場合にデフォルトで提供されます。

13.2. null セーフ

Kotlin の主要な機能の 1 つは、null-safety (英語) です。問題を実行時まで延期して NullPointerException を検出するのではなく、コンパイル時に null 値を処理します。これは、Optional のようなラッパーのコストを支払うことなく、バグの一般的な原因を排除できます。また、Kotlin では、Kotlin の null の安全性に関するこの包括的なガイド (英語) で説明されているように、null 可能な値を持つ関数構造を使用できます。

Java では、型システムで null の安全性を表現することはできませんが、Spring Framework、Spring Data、および Reactor は、ツールに適したアノテーションを通じて API の null の安全性を提供するようになりました。デフォルトでは、Kotlin で使用される Java API の型は、null チェックが緩和されたプラットフォーム型として認識 (英語) されます。 nullability アノテーションと組み合わせた Kotlin による JSR 305 アノテーションのサポート (英語) は、Kotlin の関連する Spring API に null の安全性を提供します。

JSR 305 チェックは、-Xjsr305 コンパイラーフラグに次のオプションを追加することで構成できます。-Xjsr305={strict|warn|ignore} デフォルトの動作は -Xjsr305=warn と同じです。strict 値は、Spring API から推測された Kotlin 型で null の安全性を考慮に入れる必要がありますが、Spring API の null 可能性宣言はマイナーリリース間でも発展する可能性があり、今後さらにチェックが追加される可能性があるという知識とともに使用する必要があります)。

ジェネリクス型の引数、可変引数、配列要素の nullability はまだサポートされていません。最新情報については、SPR-15942 (英語) を参照してください。また、Spring Boot の独自の API にはまだアノテーションが付けられていない [GitHub] (英語) ことに注意してください。

13.3. Kotlin API

13.3.1. runApplication

Spring Boot は、次の例に示すように、runApplication<MyApplication>(*args) でアプリケーションを実行する慣用的な方法を提供します。

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

@SpringBootApplication
class MyApplication

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

これは SpringApplication.run(MyApplication::class.java, *args) のドロップイン置換です。また、次の例に示すように、アプリケーションをカスタマイズできます。

runApplication<MyApplication>(*args) {
    setBannerMode(OFF)
}

13.3.2. 拡張

Kotlin 拡張機能 (英語) は、追加機能を使用して既存のクラスを継承する機能を提供します。Spring Boot Kotlin API は、これらの拡張機能を利用して、既存の API に新しい Kotlin 固有の便利な機能を追加します。

Spring Framework の RestOperations に対して Spring Framework によって提供されるものと同様の TestRestTemplate 拡張機能が提供されます。特に、拡張機能により、Kotlin の型指定されたパラメーターを利用できるようになります。

13.4. 依存関係の管理

異なるバージョンの Kotlin 依存関係のクラスパスへの混在を避けるために、Spring Boot は Kotlin BOM をインポートします。

Maven では、kotlin.version プロパティを設定することで Kotlin バージョンをカスタマイズでき、kotlin-maven-plugin のプラグイン管理が提供されます。Gradle を使用すると、Spring Boot プラグインは kotlin.version を Kotlin プラグインのバージョンに自動的に位置合わせします。

Spring Boot は、Kotlin コルーチン BOM をインポートすることにより、コルーチンの依存関係のバージョンも管理します。バージョンは、kotlin-coroutines.version プロパティを設定することでカスタマイズできます。

start.spring.io に少なくとも 1 つのリアクティブ依存関係がある Kotlin プロジェクトをブートストラップする場合、org.jetbrains.kotlinx:kotlinx-coroutines-reactor 依存関係がデフォルトで提供されます。

13.5. @ConfigurationProperties

@ConfigurationProperties は、コンストラクターバインディングと組み合わせて使用すると、次の例に示すように、不変の val プロパティを持つデータクラスをサポートします。

@ConfigurationProperties("example.kotlin")
data class KotlinExampleProperties(
        val name: String,
        val description: String,
        val myService: MyService) {

    data class MyService(
            val apiToken: String,
            val uri: URI
    )
}

Java との相互運用性の制限により、値クラスのサポートは制限されています。特に、値クラスのデフォルト値に依存すると、構成プロパティのバインディングでは機能しません。このような場合は、代わりにデータクラスを使用する必要があります。

アノテーションプロセッサーを使用して独自のメタデータを生成するには、kapt を spring-boot-configuration-processor 依存関係で構成する必要があります (英語) 。kapt が提供するモデルの制限により、一部の機能(デフォルト値の検出や非推奨のアイテムなど)が機能しないことに注意してください。

13.6. テスト

JUnit 4 を使用して Kotlin コードをテストすることは可能ですが、JUnit 5 はデフォルトで提供されており、推奨されています。JUnit 5 では、テストクラスを 1 回インスタンス化し、クラスのすべてのテストに再利用できます。これにより、非静的メソッドで @BeforeAll および @AfterAll アノテーションを使用できるようになり、Kotlin に適しています。

Kotlin クラスをモックするには、MockK (英語) をお勧めします。Mockito 固有の @MockBean および @SpyBean アノテーションに相当する MockK が必要な場合は、同様の @MockkBean および @SpykBean アノテーションを提供する SpringMockK [GitHub] (英語) を使用できます。

13.7. リソース

13.7.2. サンプル

14. SSL

Spring Boot は、安全な通信をサポートするために、いくつかの種類の接続に適用できる SSL 信頼マテリアルを構成する機能を提供します。プレフィックス spring.ssl.bundle が付いた構成プロパティを使用して、信頼マテリアルと関連情報の名前付きセットを指定できます。

14.1. Java KeyStore ファイルを使用した SSL の構成

プレフィックス spring.ssl.bundle.jks の付いた構成プロパティを使用すると、Java keytool ユーティリティで作成され、JKS または PKCS12 形式の Java KeyStore ファイルに保存された信頼マテリアルのバンドルを構成できます。各バンドルには、バンドルを参照するために使用できるユーザー指定の名前があります。

組み込み Web サーバーを保護するために使用される場合、keystore は通常、次の例に示すように、証明書と秘密鍵を含む Java KeyStore で構成されます。

Properties
spring.ssl.bundle.jks.mybundle.key.alias=application
spring.ssl.bundle.jks.mybundle.keystore.location=classpath:application.p12
spring.ssl.bundle.jks.mybundle.keystore.password=secret
spring.ssl.bundle.jks.mybundle.keystore.type=PKCS12
Yaml
spring:
  ssl:
    bundle:
      jks:
        mybundle:
          key:
            alias: "application"
          keystore:
            location: "classpath:application.p12"
            password: "secret"
            type: "PKCS12"

クライアント側の接続を保護するために使用される場合、truststore は通常、次の例に示すようにサーバー証明書を含む Java KeyStore で構成されます。

Properties
spring.ssl.bundle.jks.mybundle.truststore.location=classpath:server.p12
spring.ssl.bundle.jks.mybundle.truststore.password=secret
Yaml
spring:
  ssl:
    bundle:
      jks:
        mybundle:
          truststore:
            location: "classpath:server.p12"
            password: "secret"

サポートされているプロパティの完全なセットについては、JksSslBundleProperties [GitHub] (英語) を参照してください。

14.2. PEM エンコードされた証明書を使用した SSL の構成

プレフィックス spring.ssl.bundle.pem が付いた構成プロパティを使用して、PEM エンコードされたテキストの形式で信頼マテリアルのバンドルを構成できます。各バンドルには、バンドルを参照するために使用できるユーザー指定の名前があります。

組み込み Web サーバーを保護するために使用される場合、keystore は通常、次の例に示すように証明書と秘密鍵を使用して構成されます。

Properties
spring.ssl.bundle.pem.mybundle.keystore.certificate=classpath:application.crt
spring.ssl.bundle.pem.mybundle.keystore.private-key=classpath:application.key
Yaml
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          keystore:
            certificate: "classpath:application.crt"
            private-key: "classpath:application.key"

クライアント側の接続を保護するために使用される場合、truststore は通常、次の例に示すようにサーバー証明書を使用して構成されます。

Properties
spring.ssl.bundle.pem.mybundle.truststore.certificate=classpath:server.crt
Yaml
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          truststore:
            certificate: "classpath:server.crt"

PEM コンテンツは、certificate プロパティと private-key プロパティの両方に直接使用できます。プロパティ値に BEGIN および END マーカーが含まれている場合、リソースの場所ではなく PEM コンテンツとして扱われます。

次の例は、トラストストア証明書を定義する方法を示しています。

Properties
spring.ssl.bundle.pem.mybundle.truststore.certificate=\
-----BEGIN CERTIFICATE-----\n\
MIID1zCCAr+gAwIBAgIUNM5QQv8IzVQsgSmmdPQNaqyzWs4wDQYJKoZIhvcNAQEL\n\
BQAwezELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCVN0YXRlTmFtZTERMA8GA1UEBwwI\n\
...\n\
V0IJjcmYjEZbTvpjFKznvaFiOUv+8L7jHQ1/Yf+9c3C8gSjdUfv88m17pqYXd+Ds\n\
HEmfmNNjht130UyjNCITmLVXyy5p35vWmdf95U3uEbJSnNVtXH8qRmN9oK9mUpDb\n\
ngX6JBJI7fw7tXoqWSLHNiBODM88fUlQSho8\n\
-----END CERTIFICATE-----\n
Yaml
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          truststore:
            certificate: |
              -----BEGIN CERTIFICATE-----
              MIID1zCCAr+gAwIBAgIUNM5QQv8IzVQsgSmmdPQNaqyzWs4wDQYJKoZIhvcNAQEL
              BQAwezELMAkGA1UEBhMCWFgxEjAQBgNVBAgMCVN0YXRlTmFtZTERMA8GA1UEBwwI
              ...
              V0IJjcmYjEZbTvpjFKznvaFiOUv+8L7jHQ1/Yf+9c3C8gSjdUfv88m17pqYXd+Ds
              HEmfmNNjht130UyjNCITmLVXyy5p35vWmdf95U3uEbJSnNVtXH8qRmN9oK9mUpDb
              ngX6JBJI7fw7tXoqWSLHNiBODM88fUlQSho8
              -----END CERTIFICATE-----

サポートされているプロパティの完全なセットについては、PemSslBundleProperties [GitHub] (英語) を参照してください。

14.3. SSL バンドルの適用

プロパティを使用して構成すると、Spring Boot によって自動構成されるさまざまな種類の接続の構成プロパティで SSL バンドルを名前で参照できるようになります。詳細については、組み込み Web サーバーデータテクノロジ、および REST クライアントに関するセクションを参照してください。

14.4. SSL バンドルの使用

Spring Boot は、spring.ssl.bundle プロパティを使用して構成された各名前付きバンドルへのアクセスを提供する、型 SslBundles の Bean を自動構成します。

SslBundle は、自動構成された SslBundles Bean から取得でき、クライアントライブラリで SSL 接続を構成するために使用されるオブジェクトの作成に使用できます。SslBundle は、次の SSL オブジェクトを取得するための階層化されたアプローチを提供します。

  • getStores() は、キーストアとトラストストアの java.security.KeyStore インスタンスへのアクセスと、必要なキーストアのパスワードを提供します。

  • getManagers() は、java.net.ssl.KeyManagerFactory インスタンスと java.net.ssl.TrustManagerFactory インスタンス、およびそれらが作成する java.net.ssl.KeyManager 配列と java.net.ssl.TrustManager 配列へのアクセスを提供します。

  • createSslContext() は、新しい java.net.ssl.SSLContext インスタンスを取得する便利な方法を提供します。

さらに、SslBundle は、使用されているキー、使用するプロトコル、SSL エンジンに適用する必要があるオプションに関する詳細を提供します。

次の例は、SslBundle を取得し、それを使用して SSLContext を作成する方法を示しています。

Java
import javax.net.ssl.SSLContext;

import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.ssl.SslBundles;
import org.springframework.stereotype.Component;

@Component
public class MyComponent {

    public MyComponent(SslBundles sslBundles) {
        SslBundle sslBundle = sslBundles.getBundle("mybundle");
        SSLContext sslContext = sslBundle.createSslContext();
        // do something with the created sslContext
    }

}
Kotlin
import org.springframework.boot.ssl.SslBundles
import org.springframework.stereotype.Component

@Component
class MyComponent(sslBundles: SslBundles) {

    init {
        val sslBundle = sslBundles.getBundle("mybundle")
        val sslContext = sslBundle.createSslContext()
        // do something with the created sslContext
    }

}

14.5. SSL バンドルのリロード

SSL バンドルは、キーマテリアルが変更されたときに再ロードできます。バンドルを使用するコンポーネントは、リロード可能な SSL バンドルと互換性がある必要があります。現在、次のコンポーネントと互換性があります。

  • Tomcat Web サーバー

  • Netty Web サーバー

リロードを有効にするには、次の例に示すように、構成プロパティを介してオプトインする必要があります。

Properties
spring.ssl.bundle.pem.mybundle.reload-on-update=true
spring.ssl.bundle.pem.mybundle.keystore.certificate=file:/some/directory/application.crt
spring.ssl.bundle.pem.mybundle.keystore.private-key=file:/some/directory/application.key
Yaml
spring:
  ssl:
    bundle:
      pem:
        mybundle:
          reload-on-update: true
          keystore:
            certificate: "file:/some/directory/application.crt"
            private-key: "file:/some/directory/application.key"

ファイルウォッチャーがファイルを監視し、ファイルが変更されると、SSL バンドルがリロードされます。これにより、消費側コンポーネントでのリロードがトリガーされます。Tomcat は、SSL 対応コネクター内の証明書をローテーションします。

spring.ssl.bundle.watch.file.quiet-period プロパティを使用して、ファイルウォッチャーの静止期間 (変更が存在しないことを確認するため) を構成できます。

15. 次のステップ

このセクションで説明したクラスについて詳しく知りたい場合は、Spring Boot API ドキュメントを参照するか、ソースコードを直接 [GitHub] (英語) 参照してください。具体的な質問がある場合は、使い方セクションを参照してください。

Spring Boot のコア機能に慣れている場合は、引き続き本番環境向けの機能について読み進めてください。