SpringBootのapplication.ymlのデータをenumにマッピングする方法(SpringBoot)

エキサイト株式会社メディアプラットフォーム事業エンジニアの佐々木です。

Javaenumは大変便利でかなり活用していますが、SpringBootなどのDIコンテナと絡めたときに、enumはDIできないのでapplication.ymlなどの環境ごとの動的データが使用できないことがあります。今回はその1つの解決方法についてご紹介します。

application.yml

下記のようなapplication.ymlがあるとします。

app:
  type:
    one:two:

Javaコード

結論は下記のようなコードになります。

import jakarta.annotation.PostConstruct;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class TypeComponent {

    private final TypeValue typeValue;

    public TypeComponent(TypeValue typeValue) {
        this.typeValue = typeValue;
    }

    // application.ymlから"app"配下を読み取る
    @ConfigurationProperties(prefix = "app")
    record TypeValue(Map<String,String> type){}

    public String getType(Type type) {
        return type.getTypeValue(typeValue);
    }

    // classの中でenumを宣言する
    public enum Type {
        ONE("one"),
        TWO("two");

        private final String value;

        Type(String type) {
            this.value = type;
        }
        // application.ymlの値を取得するときに、TypeValueが必要なので、引数で渡すようにする
        public String getTypeValue(TypeValue typeValue) {
            // 引数でthisを使ってるのがポイント
            return typeValue.type.get(this.value);
        }
    }

    // DIの初期化が終わったあとに実行して確認するために設置
    @PostConstruct
    public void init() {
        System.out.println("TypeComponent.Type.ONE のyamlの値:" + getType(Type.ONE));
        System.out.println("TypeComponent.Type.TWO のyamlの値:" + getType(Type.TWO));
    }
}

// 出力
TypeComponent.Type.ONE のyamlの値:壱
TypeComponent.Type.TWO のyamlの値:弐

ポイントは、2つあります。

  • 通常のクラスを@ComponentでDI対象にして、その中でenumを宣言する
  • enumを値を使用しながら、application.ymlのデータを取り出すメソッドの引数に、application.ymlからDIで取得したオブジェクト(TypeValue)のインスタンスをセットする

上記のコードで enumにapplication.yml の値をマッピングできます。

まとめ

上記のコードでenumとSpring/DIのいいとこ取りができますし、そんなに複雑でもないのでぜひお試しください。