Spring Bootの設定はどこから来るのか ― 外部設定・Profile・型安全な読み込み
application.propertiesでは8081と書いたのに、実際には18081で起動した。Spring Bootでは、同じ設定キーをファイル、環境変数、コマンドライン引数などから渡せます。便利な一方、最終値の出所を追えないと、環境だけで起きる不具合になります。
この回では、設定を「どのファイルに書くか」ではなく、どのPropertySourceが最終値を決めたかとして読みます。
この記事でわかること
- 外部設定の代表的な優先順位
- Profileが優先順位そのものではない理由
-
@Valueと@ConfigurationPropertiesの使い分け - Secretと通常設定を分ける考え方
設定は、後から上位の値で上書きされる
たとえばJAR内に次の設定を入れます。
server.port=8081
order.notification.enabled=false
同じJARを、環境変数だけ変えて起動できます。
$env:SERVER_PORT='18082'
java -jar target/order-sample-0.0.1-SNAPSHOT.jar
さらにコマンドライン引数を渡すと、そちらが優先されます。
java -jar target/order-sample-0.0.1-SNAPSHOT.jar --server.port=18081
Spring Boot 3.5.16で確認すると、ファイルだけなら8081、環境変数を加えると18082、さらに引数を加えると18081で起動しました。これは特別なポート機能ではなく、外部設定の優先順位による結果です。
図は実務で衝突しやすい6段を抜粋しています。テスト用プロパティ、SPRING_APPLICATION_JSON、JavaのSystem propertiesなども含む完全な順序は、公式のExternalized Configurationで確認してください。
Profileは環境名のスイッチ
# application-staging.properties
order.notification.enabled=true
order.notification.endpoint=https://example.invalid/staging-notifications
$env:SPRING_PROFILES_ACTIVE='staging'
java -jar target/order-sample-0.0.1-SNAPSHOT.jar
Profileを有効にすると、共通設定にProfile別設定が重ねて読み込まれます。ただし、Profileが最上位になるわけではありません。その後も環境変数やコマンドライン引数で上書きできます。
dev、staging、productionという名前だけで安全性は決まりません。何を切り替えるProfileなのか、複数Profileを同時に有効にするか、優先順をどうするかを運用手順へ残します。
まとまりのある設定は型として受け取る
一つの値を読むだけなら@Valueでも書けます。
@Value("${order.notification.enabled:false}")
private boolean notificationEnabled;
項目が増えると、キーが各クラスへ散らばります。注文通知というまとまりで受けるなら、@ConfigurationPropertiesを使います。
@ConfigurationProperties(prefix = "order.notification")
@Validated
public record NotificationProperties(
boolean enabled,
@NotNull URI endpoint,
@Min(1) int retryCount) {
}
@ConfigurationPropertiesScan
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
型変換とValidationが起動時に働くので、URLや回数の誤りを最初のリクエストまで持ち越しません。IDEの補完に使うメタデータも生成できます。
環境変数では表記が変わります
order.notification.retry-countは、環境変数ではORDER_NOTIFICATION_RETRYCOUNTのように変換されます。Spring Bootのrelaxed bindingが表記差を吸収しますが、どんな名前でもよいわけではありません。変換規則は公式資料で確認してください。
Secretを通常設定へ混ぜない
DBのURLや機能フラグは外部設定に向きますが、パスワードやAPIキーをGit管理するapplication-production.propertiesへ書くのは別問題です。
- 開発用のダミー値と本物のSecretを分ける
- 本番はSecret Managerやコンテナ基盤のSecret機能から注入する
- 起動ログ、Actuator、例外メッセージへ値を出さない
- 期限、更新、失効の手順も設定管理に含める
「環境変数なら安全」とも限りません。プロセス情報や診断情報から見える環境があるため、配備基盤の公開範囲を確認します。
実務ではこうなる
設定トラブルは、値そのものより出所の誤認で長引きます。調査時は次の順に追います。
- 期待したProfileが有効か
- JAR内とJAR外のどちらの設定を読んでいるか
- 環境変数や起動引数で上書きされていないか
- キー名がrelaxed bindingの規則に合っているか
-
@ConfigurationPropertiesのValidationエラーが起動ログに出ていないか
本番起動コマンドを手入力だけにせず、配備定義をコード管理すると再現性が上がります。一方、Secretの値そのものはコード管理しません。設定の名前と渡し方は再現可能にし、秘密の値は分離するのが着地点です。
次回は、HTTP入力を検証し、失敗を一貫したエラー応答へ変換します。
公式リファレンス
- Spring Boot 3.5: Externalized Configuration
- Spring Boot 3.5: Type-safe Configuration Properties
- Spring Boot 3.5: Profiles
参考文献・参照資料
- Mark Heckler, Spring Boot:立ち上げて実行する、ISBN 9798341626911(AI翻訳版):第5章の設定とアプリケーション状態の調査を参照。
- Somnath Musib, Spring Boot in Practice, Manning, ISBN 9781617298813:第2章の外部設定と設定値検証を参照。
- 田村達也『後悔しないためのSpring Boot入門書:Spring解体新書(第2版)』:Profileと設定ファイルの説明を補助参照。
書籍のコード・図・訳文は転載せず、架空の注文受付アプリへ置き換えました。優先順位と3.5固有の挙動は公式資料と実行結果を優先しています。
