エキサイト株式会社メディアプラットフォーム事業エンジニアの佐々木です。
Javaのenumは大変便利でかなり活用していますが、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のいいとこ取りができますし、そんなに複雑でもないのでぜひお試しください。