Spring Boot アプリケーション

このセクションには、Spring Boot アプリケーションに直接関連するトピックが含まれています。

独自の FailureAnalyzer を作成する

FailureAnalyzer (Javadoc) は、起動時に例外をインターセプトし、それを FailureAnalysis (Javadoc) にラップされた人間が読み取れるメッセージに変換する優れた方法です。Spring Boot は、アプリケーションコンテキスト関連の例外、JSR-303 検証などのためのこのようなアナライザーを提供します。独自に作成することもできます。

AbstractFailureAnalyzer は、FailureAnalyzer の便利な拡張機能であり、処理する例外の指定された例外型の存在を確認します。それを継承して、実装が例外が実際に存在する場合にのみ例外を処理する機会を得ることができます。何らかの理由で例外を処理できない場合は、null を返して、別の実装に例外を処理する機会を与えます。

FailureAnalyzer 実装は META-INF/spring.factories に登録する必要があります。次の例では、ProjectConstraintViolationFailureAnalyzer を登録します。

org.springframework.boot.diagnostics.FailureAnalyzer=\
com.example.ProjectConstraintViolationFailureAnalyzer
BeanFactory または Environment にアクセスする必要がある場合は、FailureAnalyzer 実装のコンストラクター引数として宣言します。

自動構成のトラブルシューティング

Spring Boot 自動構成は、「正しい動作をする」ために最善を尽くしますが、時には失敗することがあり、その理由を説明するのは難しい場合があります。

どの Spring Boot ApplicationContext でも、非常に便利な ConditionEvaluationReport が利用できます。DEBUG ログ出力を有効にすると、これを表示できます。spring-boot-actuator ( アクチュエーターの章を参照) を使用する場合は、レポートを JSON でレンダリングする conditions エンドポイントもあります。そのエンドポイントを使用してアプリケーションをデバッグし、実行時に Spring Boot によって追加された機能 (および追加されなかった機能) を確認します。

ソースコードと Javadoc を見ると、さらに多くの質問に答えることができます。コードを読むときは、次の経験則を覚えておいてください。

  • *AutoConfiguration というクラスを探して、そのソースを参照してください。@Conditional* アノテーションに特に注意して、どの機能がいつ有効になるかを調べましょう。コマンドラインに --debug を追加するか、システムプロパティ -Ddebug を追加すると、アプリで行われたすべての自動構成決定のログがコンソールに表示されます。アクチュエーターが有効になっている実行中のアプリケーションでは、同じ情報については conditions エンドポイント (/actuator/conditions または JMX の同等のもの) を参照してください。

  • @ConfigurationProperties (ServerProperties (Javadoc) など)であるクラスを探し、そこから使用可能な外部構成オプションを読み取ります。@ConfigurationProperties アノテーションには、外部プロパティのプレフィックスとして機能する name 属性があります。ServerProperties には prefix="server" があり、その構成プロパティは server.portserver.address などです。アクチュエーターが有効になっている実行中のアプリケーションで、configprops エンドポイントを確認します。

  • Binder で bind メソッドの使用を探して、緩和された方法で Environment から明示的に構成値をプルします。多くの場合、接頭辞とともに使用されます。

  • Environment に直接バインドする @Value アノテーションを探します。

  • 通常 Environment から解決されたプレースホルダーで評価される SpEL 式にレスポンスして、機能のオンとオフを切り替える @ConditionalOnExpression アノテーションを探します。

開始する前に環境または ApplicationContext をカスタマイズする

SpringApplication には、コンテキストまたは環境にカスタマイズを適用するために使用される ApplicationListeners および ApplicationContextInitializers があります。Spring Boot は、META-INF/spring.factories から内部的に使用するために、このようなカスタマイズの多くをロードします。追加のカスタマイズを登録する方法は複数あります。

  • プログラムごとに、アプリケーションごとに、SpringApplication で addListeners および addInitializers メソッドを呼び出してから実行します。

  • 宣言的に、すべてのアプリケーションについて、META-INF/spring.factories を追加し、すべてのアプリケーションがライブラリとして使用する jar ファイルをパッケージ化します。

SpringApplication はいくつかの特別な ApplicationEvents をリスナーに送信し(コンテキストが作成される前でも)、ApplicationContext によって公開されたイベントのリスナーも登録します。完全なリストについては、「Spring Boot 機能」セクションの "アプリケーションイベントとリスナー" を参照してください。

EnvironmentPostProcessor を使用して、アプリケーションコンテキストをリフレッシュする前に Environment をカスタマイズすることもできます。次の例に示すように、各実装は META-INF/spring.factories に登録する必要があります。

org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor

実装は任意のファイルをロードし、Environment に追加できます。たとえば、次の例では、クラスパスから YAML 構成ファイルをロードします。

  • Java

  • Kotlin

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;

public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {

	private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
		Resource path = new ClassPathResource("com/example/myapp/config.yml");
		PropertySource<?> propertySource = loadYaml(path);
		environment.getPropertySources().addLast(propertySource);
	}

	private PropertySource<?> loadYaml(Resource path) {
		Assert.isTrue(path.exists(), () -> "Resource " + path + " does not exist");
		try {
			return this.loader.load("custom-resource", path).get(0);
		}
		catch (IOException ex) {
			throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
		}
	}

}
import org.springframework.boot.SpringApplication
import org.springframework.boot.env.EnvironmentPostProcessor
import org.springframework.boot.env.YamlPropertySourceLoader
import org.springframework.core.env.ConfigurableEnvironment
import org.springframework.core.env.PropertySource
import org.springframework.core.io.ClassPathResource
import org.springframework.core.io.Resource
import org.springframework.util.Assert
import java.io.IOException

class MyEnvironmentPostProcessor : EnvironmentPostProcessor {

	private val loader = YamlPropertySourceLoader()

	override fun postProcessEnvironment(environment: ConfigurableEnvironment, application: SpringApplication) {
		val path: Resource = ClassPathResource("com/example/myapp/config.yml")
		val propertySource = loadYaml(path)
		environment.propertySources.addLast(propertySource)
	}

	private fun loadYaml(path: Resource): PropertySource<*> {
		Assert.isTrue(path.exists()) { "Resource $path does not exist" }
		return try {
			loader.load("custom-resource", path)[0]
		} catch (ex: IOException) {
			throw IllegalStateException("Failed to load yaml configuration from $path", ex)
		}
	}

}
Environment は、デフォルトで Spring Boot がロードするすべての通常のプロパティソースですでに準備されています。環境からファイルの場所を取得することが可能です。上記の例では、リストの最後に custom-resource プロパティソースを追加して、他の通常の場所のいずれかで定義されたキーが優先されるようにします。カスタム実装では、別の順序を定義できます。
@SpringBootApplication で @PropertySource を使用することは、Environment にカスタムリソースをロードする便利な方法のように思えるかもしれませんが、お勧めしません。このようなプロパティソースは、アプリケーションコンテキストがリフレッシュされるまで Environment に追加されません。これは、リフレッシュが開始される前に読み込まれる logging.* や spring.main.* などの特定のプロパティを構成するには遅すぎます。

ApplicationContext 階層を構築する (親またはルートコンテキストの追加)

ApplicationBuilder クラスを使用して、親 / 子 ApplicationContext 階層を作成できます。詳細については、「Spring Boot 機能」セクションの "Fluent Builder API" を参照してください。

非 Web アプリケーションを作成する

すべての Spring アプリケーションが Web アプリケーション (または Web サービス) である必要はありません。main メソッドでコードを実行すると同時に、Spring アプリケーションをブートストラップして使用するインフラストラクチャを設定する場合は、Spring Boot の SpringApplication 機能を使用できます。SpringApplication は、Web アプリケーションが必要かどうかに応じて、ApplicationContext クラスを変更します。まず最初にできることは、サーバー関連の依存関係 (サーブレット API など) をクラスパスから外すことです。それができない場合 (たとえば、同じコードベースから 2 つのアプリケーションを実行する場合) は、SpringApplication インスタンスで setWebApplicationType(WebApplicationType.NONE) を明示的に呼び出すか、applicationContextClass プロパティ (Java API 経由または外部プロパティを使用) を設定できます。ビジネスロジックとして実行するアプリケーションコードは、CommandLineRunner として実装し、@Bean 定義としてコンテキストにドロップできます。