カテゴリ: Spring 更新日: 2026/02/24

Spring Bootのコンストラクタバインディング完全解説!初心者でもわかるイミュータブル設定クラスの作り方

コンストラクタバインディング:イミュータブル設定クラスの作り方
コンストラクタバインディング:イミュータブル設定クラスの作り方

先生と生徒の会話形式で理解しよう

生徒

「Spring Bootで設定クラスを不変(イミュータブル)にしたいんですが、どうすればいいですか?」

先生

「その場合は、@ConfigurationPropertiesと一緒にコンストラクタバインディングを使うのがベストです。」

生徒

「コンストラクタバインディングってなんですか?普通のバインディングと何が違うんですか?」

先生

「それでは、イミュータブルな設定クラスを作る方法を、コンストラクタバインディングの仕組みと一緒に解説していきましょう。」

1. コンストラクタバインディングとは?

1. コンストラクタバインディングとは?
1. コンストラクタバインディングとは?

Spring Bootで設定クラスを定義するとき、多くの場合は@ConfigurationProperties@Componentを組み合わせて、セッターで値を設定します。しかし、それではクラスのプロパティが変更可能(ミュータブル)になります。

コンストラクタバインディングは、finalフィールドとコンストラクタを使って、不変(イミュータブル)な設定クラスを作るための仕組みです。

Spring Boot 2.2以降で正式にサポートされており、設計上の安全性が向上します。

2. コンストラクタバインディングのメリット

2. コンストラクタバインディングのメリット
2. コンストラクタバインディングのメリット

コンストラクタバインディングを使う主なメリットは以下のとおりです。

  • クラスのプロパティがfinalで定義されるため、再代入を防げる
  • 不変オブジェクトになることで、スレッドセーフになる
  • コンパイル時に初期化漏れが検出できる
  • テストやDIがしやすく、保守性が高い

つまり、より堅牢で信頼性の高い設定クラスが作れます。

3. コンストラクタバインディングの基本構成

3. コンストラクタバインディングの基本構成
3. コンストラクタバインディングの基本構成

まずは、application.ymlに次のような設定を書きます。


sample:
  service:
    name: ExampleService
    port: 8080

次にJavaクラスを定義します。


@ConfigurationProperties(prefix = "sample.service")
@ConstructorBinding
public class ServiceProperties {

    private final String name;
    private final int port;

    public ServiceProperties(String name, int port) {
        this.name = name;
        this.port = port;
    }

    public String getName() {
        return name;
    }

    public int getPort() {
        return port;
    }
}

このようにすれば、プロパティの変更を禁止したイミュータブルな設定クラスになります。

4. @EnableConfigurationPropertiesで登録する

4. @EnableConfigurationPropertiesで登録する
4. @EnableConfigurationPropertiesで登録する

コンストラクタバインディングを使うクラスは、@Componentを付けずに、@EnableConfigurationPropertiesで登録します。


@Configuration
@EnableConfigurationProperties(ServiceProperties.class)
public class Config {
}

この方法により、Spring Bootの自動設定に依存せずに、明示的に設定クラスをBean登録できます。

5. Spring Bootでの利用例

5. Spring Bootでの利用例
5. Spring Bootでの利用例

設定クラスを実際のコントローラーなどで利用するには、コンストラクタインジェクションを使います。


@RestController
public class SampleController {

    private final ServiceProperties serviceProperties;

    public SampleController(ServiceProperties serviceProperties) {
        this.serviceProperties = serviceProperties;
    }

    @GetMapping("/info")
    public String info() {
        return serviceProperties.getName() + " - " + serviceProperties.getPort();
    }
}

このようにすれば、設定ファイルの内容をクラスにバインドし、Webアプリケーションから動的に利用することができます。

6. @ConstructorBindingの注意点

6. @ConstructorBindingの注意点
6. @ConstructorBindingの注意点

@ConstructorBindingを使用するには、以下の条件を満たす必要があります。

  • Javaクラスは@Componentを付けない
  • 明示的に@EnableConfigurationPropertiesでBean登録する
  • Spring Bootのバージョンが2.2以降であること

また、インナークラスやネストした設定を使う場合も、すべてのクラスで同様にfinalとコンストラクタを使う必要があります。

7. ネスト構造でのコンストラクタバインディング

7. ネスト構造でのコンストラクタバインディング
7. ネスト構造でのコンストラクタバインディング

設定ファイルにネストされた構造がある場合も、同様にクラスを分けてコンストラクタバインディングを適用できます。


sample:
  service:
    name: NestedService
    security:
      token: abc123
      expire: 60

public class Security {

    private final String token;
    private final int expire;

    public Security(String token, int expire) {
        this.token = token;
        this.expire = expire;
    }

    // getter
}

@ConfigurationProperties(prefix = "sample.service")
@ConstructorBinding
public class ServiceProperties {

    private final String name;
    private final Security security;

    public ServiceProperties(String name, Security security) {
        this.name = name;
        this.security = security;
    }

    // getter
}

このようにネストしていても、イミュータブルで保守性の高い設計が可能です。

8. バリデーションとの組み合わせ

8. バリデーションとの組み合わせ
8. バリデーションとの組み合わせ

@Validatedはコンストラクタバインディングと同時には使用できません。ただし、JSR-303のバリデーションアノテーションを使った検証は可能です。

検証のロジックを自前で作りたい場合は、バインディング後に別途チェック処理を実装するか、ファクトリーメソッドで制御するのも一つの方法です。

9. レコード(record)との組み合わせ

9. レコード(record)との組み合わせ
9. レコード(record)との組み合わせ

Java 14以降ではrecordを使って、もっと簡潔にイミュータブルな設定クラスを作成できます。


@ConfigurationProperties(prefix = "sample.service")
@ConstructorBinding
public record ServiceProperties(String name, int port) {
}

レコード型は自動的にコンストラクタを持つため、非常に相性が良く、よりシンプルでモダンな記述が可能になります。

カテゴリの一覧へ
新着記事
New1
Spring
Spring Bootのコンストラクタバインディング完全解説!初心者でもわかるイミュータブル設定クラスの作り方
新規投稿
New2
Java
JavaのStringクラスとcharAtメソッドを完全解説!初心者でも理解できる使い方
更新記事
New3
Spring
SpringDataJPAのJPAクエリメソッド「IgnoreCase」の使い方を完全ガイド!初心者向け解説
更新記事
New4
Servlet
JavaのHttpServletRequestWrapperのgetHeadersの使い方を完全ガイド!複数のHTTPヘッダー値を取得する方法
更新記事
人気記事
No.1
Java&Spring記事人気No1
Spring
Spring BootとJavaの互換性一覧!3.5/3.4/3.3はJava 21・17に対応してる?
No.2
Java&Spring記事人気No2
Java
JavaのBooleanクラスの使い方を完全ガイド!初心者でもわかる真偽値の操作
No.3
Java&Spring記事人気No3
JSP
JSPの基本タグ一覧と使い方まとめ!実務で使えるタグを紹介
No.4
Java&Spring記事人気No4
JSP
JSPでif文・for文を使う方法!初心者でもわかるJavaとの違いと使い方
No.5
Java&Spring記事人気No5
Spring
Springの@Componentアノテーションの使い方を徹底解説!初心者でもわかるSpring Boot入門
No.6
Java&Spring記事人気No6
Spring
SpringDataJPAのJPAクエリメソッド「EndingWith」の使い方を完全ガイド!初心者向け解説
No.7
Java&Spring記事人気No7
Spring
SpringのBindingResultを完全ガイド!初心者でもわかる入力チェックとエラー処理
No.8
Java&Spring記事人気No8
Java
JavaのIOExceptionクラス徹底解説!初心者向けファイル入出力エラー対策ガイド