SpringBootで設定ファイル(application.yaml)を一括で読み込む

エキサイト株式会社エンジニアの佐々木です。SpringBootでの設定ファイル(application.yaml)を一括で読む方法のメモになります。

前提

SpringBoot2.4以上で検証しています。

起動クラスの設定

ソースコードは下記になります。

起動クラスに@ConfigurationPropertiesScanを付与します。これで、@ConfigurationPropertiesアノテーションを読みにいきます。

@SpringBootApplication
@ConfigurationPropertiesScan  // ConfigurationPropertiesを読みにいくおまじない
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

単一項目な設定ファイル

設定ファイルの項目名と変数名が一致していればバインドされます。

設定ファイル(appliation.yaml)

設定ファイルは下記になります。

env:
  host: local
  port: 8080

読み取りクラス

読み取りクラスは下記のように定義します。

@Getter
@RequiredArgsConstructor
@ConstructorBinding          // この設定がないと Setterが必要になるのでつけておく
@ConfigurationProperties(prefix = "env")   // prefixで指定された部分のyamlを読みいく
public class Config {
    private final String host;
    private final Integer port;
}

@ConfigurationPropertiesアノテーションapplication.yamlのどこを読むかを設定します。@ConstructorBindingアノテーションで、setterがなくても値がセットされるようにします(つけておかないとSetterメソッドが必要になります)。@Getter@RequiredArgsConstructorLombokアノテーションです。Getterの生成とコンストラクタの定義を省略できます。yamlの中のプロパティ名とクラスのプロパティ名を合わせると、バインドしてくれます。型は気にしなくても、StringやIntegerくらいなら対応してくれます。設定されたものは、DIをすれば、使えます。

出力

{
"host": "local",
"port": 8080
}

Key-Value型の読み取り

Key-Value形式の設定は、Map型を使いKey-Valueをオブジェクトにバインドします。

設定ファイル

regionの中にjausのようなkey-valueのファイルがあるとします。

env:
  host: local
  port: 8080
  region:
    ja: 日本
    us: アメリカ

読み取りクラス

読み取りでは、Map型を使いJavaオブジェクトに変換していきます。

@Getter
@RequiredArgsConstructor
@ConstructorBinding
@ConfigurationProperties(prefix = "env")
public class Config {
    private final String host;
    private final Integer port;
    private final Map<String,String> region; // Map型で定義(ジェネリクスは相応の型を指定)
}

上記で、region変数にKey-Value型のデータがバインドされます。

出力

{
"host": "local",
"port": 8080,
"region": {
    "ja": "日本",
    "us": "アメリカ"
    }
}

プロパティがネストされたapplication.yaml

ネストされた設定ファイルもバインド可能です。項目名と変数名が一致していれば自動的にバインドしてくれます。

設定ファイル

ネストされた設定ファイルです。

env:
  host: local
  port: 8080
  people:
    - name: hogehoge
      age: 18
    - name: fugafuga
      age: 30

読み取りクラス

階層がある場合は、staticな内部クラスを書くか、外部クラスに定義して型を指定するかになります。変数名が一致すればクラスに合わせて読み込みまれます。

@Getter
@RequiredArgsConstructor
@ConstructorBinding
@ConfigurationProperties(prefix = "env")
public static class Config {
    private final String host;
    private final Integer port;
    private final List<People> people;

    @Getter
    @RequiredArgsConstructor
    static class People {
        private String name;
        private Integer age;
    }
}

staticな内部クラスでも@Getter、@RequiredArgsConstructorアノテーションは必要になります。

出力

{
  "host": "local",
  "port": 8080,
  "region": {
    "ja": "日本",
    "us": "アメリカ"
  },
  "people": [
    {
      "name": "hogehoge",
      "age": 18
    },
    {
      "name": "fugafuga",
      "age": 30
    }
  ]
}

まとめ

@Valueで1つずつ読み込む方法もありますが、記述が多くなるので、クラス定義だけでできる方法を記載します。Yamlとの脳内変換が多くなってくるので、ネストの深さがでてくると、冗長でも@Valueの方が楽な場合もあるかもしれません。適材適所でお使いください。

最後に

エキサイト株式会社では、新卒・中途(大卒・高専卒・高卒問わず)バックエンドエンジニア・アプリエンジニア・フロントエンジニア・クリエイティブを募集しております。興味がありましたらご連絡をお待ちしております。

カジュアル面談はこちらになります! meety.net

募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com