Spring Bootで設定値を読み込むとき、単一の値なら@Value、関連する複数項目をまとめて管理するなら@ConfigurationPropertiesが基本的な選択肢です。@ConfigurationPropertiesは型安全なオブジェクトへまとめてバインドし、設定名の表記ゆれにも対応します。一方の@Valueは個別の値を注入し、SpEL式も利用できます。環境別の設定値を扱う場合は、注入方法だけでなく、設定値の定義場所と秘密情報の扱いも分けて確認しましょう。
@Valueと@ConfigurationPropertiesは何が違う?
| 比較 | @Value | @ConfigurationProperties |
|---|---|---|
| 向いている規模 | 少数・個別の値 | 同じprefixの複数設定 |
| バインド | プレースホルダー・SpELを利用 | 階層化したオブジェクトへの型安全なバインド |
| Relaxed binding | 限定的。正規形のキー指定を推奨 | 対応 |
| SpEL | 利用できる | 直接は対象外 |
| 設定メタデータ | 直接のサポートなし | メタデータ生成に対応 |
| 構造とレビュー | 設定数が増えると注入先が分散しやすい | 定義クラスへまとめやすい |
Spring Boot公式ドキュメントも、独自の設定グループを作る場合は@ConfigurationPropertiesを使って構造化する方法を推奨しています。違いは単純な速度比較ではなく、管理する設定の種類と責務です。
用語解説:Relaxed binding
app.mail.host、環境変数APP_MAIL_HOSTなど、記法の異なるプロパティ名を同じ設定項目へ対応づける仕組み。@Valueにも限定的な対応があります。
@Valueで一つの設定値を読み込む
単一の設定項目なら@Valueが簡潔です。application.ymlに値を定義し、Spring管理Beanのフィールドやコンストラクタ引数から参照できます。
# application.yml
app:
mail:
host: smtp.example.invalid
port: 2525
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MailHostPrinter {
private final String host;
public MailHostPrinter(@Value("${app.mail.host}") String host) {
this.host = host;
}
public String host() {
return host;
}
}
ここでのsmtp.example.invalidは説明用のドメインです。実接続は想定していません。なお、存在しないキーを指定すると設定解決に失敗する場合があります。既定値を許容する設計なら、プレースホルダー内でデフォルトを指定できます。
複数項目を@ConfigurationPropertiesでまとめる
メール接続先など関連する設定が増える場合は、1つの型にまとめると値の所在が明確になります。Spring Boot 3以降ではrecordによるコンストラクタバインディングを利用できます。
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "app.mail")
public record MailSettings(String host, int port) {
}
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@SpringBootApplication
@ConfigurationPropertiesScan
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
import org.springframework.stereotype.Service;
@Service
public class MailService {
private final MailSettings settings;
public MailService(MailSettings settings) {
this.settings = settings;
}
public String host() {
return settings.host();
}
}
@ConfigurationPropertiesScanで定義クラスを検出します。ここではDemoApplicationのパッケージ配下にMailSettingsがある前提です。recordは必要な値をコンストラクタで受け取るため、使う側はまとまった型を注入できます。設定対象クラスを通常の@Componentや@Beanで生成すると、同じ形のコンストラクタバインディングにならない場合がある点にも注意してください。
環境変数とapplication.ymlの管理
本番・開発環境で値を切り替えるときは、設定のソースとバインド方法を分けて考えます。例えばapp.mail.hostを環境変数APP_MAIL_HOSTで上書きする構成を検討できます。
| 設定ソース例 | 目的 | 注意点 |
|---|---|---|
| application.yml | 共通の既定値や開発用設定 | 機密情報をGitへコミットしない |
| application-prod.yml | プロファイル別の値 | どのプロファイルが有効か確認する |
| 環境変数 | 実行環境での差し替え | 命名規則・デプロイ設定を検証する |
| Secret Manager等 | 認証情報などの保護 | 権限と運用方針を別途整備する |
@ConfigurationPropertiesを使っただけで認証情報が安全になるわけではありません。パスワード・トークン等は平文の設定ファイルへ安易に保存せず、運用環境の秘密情報管理を利用してください。
@Valueの使いすぎで起こりやすい問題
設定が多いプロジェクトでは、複数の@Serviceや@Componentへ@Valueを散らすと、どの画面や機能が何のキーに依存しているか追いにくくなります。個別の注入が悪いのではなく、同じグループの設定が複数の場所へ分散するのが問題です。
- 一つのクラスに関連するキーが多いなら@ConfigurationPropertiesで集約する。
- 設定名を変更するときは参照箇所を把握する。
- 型変換エラーが起きたら、値と対象フィールドの型を確認する。
- 必須項目には適切な検証を導入し、設定不足を起動時に検知できるようにする。
@ValidatedやJakarta Bean Validationでバリデーションを付ける方法もありますが、依存ライブラリやBootのバージョンを確認して利用してください。
@ConfigurationPropertiesが注入されないときの確認
- @ConfigurationPropertiesScanか@EnableConfigurationPropertiesで型が登録されているか。
- スキャン対象パッケージがアプリケーション配下にあるか。
- prefixとapplication.ymlの階層が一致しているか。
- コンストラクタバインディングを使う型が通常の@Component生成Beanになっていないか。
- プロファイル別設定の読み込み順や環境変数が想定と合っているか。
- 秘密情報をログで全文表示していないか。
「設定が反映されない」という症状でも、原因はアノテーションの選択、Bean登録、設定ソースの優先順位などに分かれます。値を公開ログへ出すのではなく、設定キー・登録状態・アプリ起動時のエラーから切り分けましょう。
選定のための判断表
| 状況 | 判断 |
|---|---|
| メールのhostなど一つの値を読みたい | @Valueも候補 |
| 関連する複数の設定を型安全に保持したい | @ConfigurationPropertiesを優先 |
| SpELで動的な式を使いたい | @Valueが向いている |
| 環境別の一連の設定を共有したい | @ConfigurationPropertiesでまとめる |
| 設定が1個しかなく構造化の効果が薄い | 無理に設定クラスを増やさない |
新しく設計するときは、設定の数だけでなく、同じ概念に属するか、型の整合性や環境差分を管理する必要があるかを基準に選んでください。
関連するSpring Bootの記事
アノテーション全体の役割を整理したいときは既存記事、設定オブジェクトをSpring管理Beanへ渡す仕組みを理解したいときはDIの解説が役立ちます。
(Springのアノテーションの役割については『Spring Bootのよく使われるアノテーションとは?初心者必見の解説と活用法』をご参照ください)
(設定クラスをBeanへ注入する仕組みについては『Spring Boot の@Autowired はなぜ動く?NullPointerException 対策から学ぶ DI/IoC の基本と「正しい」コンポーネント管理術』をご参照ください)
よくある疑問とまとめ
@Valueは古いので使わない方がいいですか?
いいえ。少数の個別設定やSpELが必要な場面では有効です。複数の関連設定をまとめるなら@ConfigurationPropertiesが向きます。
@ConfigurationPropertiesに@Componentを付ければ十分ですか?
JavaBean方式なら構成によって使えますが、recordなどのコンストラクタバインディングを使う場合は、@ConfigurationPropertiesScanや@EnableConfigurationPropertiesを利用します。
@ValueにRelaxed bindingはありませんか?
限定的にあります。公式ドキュメントはプレースホルダーのキーを小文字kebab-caseなどの正規形で指定することを推奨しています。
@Valueと@ConfigurationPropertiesは二者択一ではありません。単発の設定値は簡潔に、関連設定群は型としてまとめることが実務での判断基準です。環境ごとの上書きや秘匿情報の扱いは別の設計として確認しましょう。
現在の@Value指定を点検し、同じprefixで繰り返し使う設定があれば構造化できるか考えてみてください。