application.yml
から値を取得する方法は主に以下の3つのやり方があるようです。
-
@Value
アノテーション -
Environment
クラス -
@ConfigurationProperties
アノテーション
それぞれの方法をkotlinで試してみます。
環境
- JDK: 1.8
- kotlin: 1.3
- Spring Boot 2.1.4.RELEASE
以下のapplication.ymlから値を取得します。
app-conf:
numeric-param: 10
string-param: hogehoge
structure-param:
param1: hoge
param2: fuga
Value
@Value
アノテーションを使用すると簡単に値を取得できます。
@Component
class ValueComponent {
@Value("\${app-conf.numeric-param}")
val numericParam = 0
@Value("\${app-conf.string-param}")
val stringParam = ""
@Value("\${app-conf.undefined-param:defaultValue}")
val undefinedParam = ""
@Value("\${app-conf.structure-param.param1}")
val structureParam1 = ""
@Value("\${app-conf.structure-param.param2}")
val structureParam2 = ""
fun main() {
println("numericParam=$numericParam")
println("stringParam=$stringParam")
println("undefinedParam=$undefinedParam")
println("structureParam.param1=$structureParam1")
println("structureParam.param2=$structureParam2")
}
}
numericParam=10
stringParam=hogehoge
undefinedParam=defaultValue
structureParam.param1=hoge
structureParam.param2=fuga
@Value
に渡す文字列は\${}
のようにエスケープする必要があります。
またvalで定義した変数であっても値をセットしてくれますが、変数定義時にセットしている値は無視されます。
デフォルト値を設定したい場合は\${変数名:デフォルト値}
のようにします。
Environment
取得するパラメータを動的に変更したい場合はEnvironment.getProperty()
が使えます。
@Component
class EnvironmentComponent {
@Autowired
lateinit var environment: Environment
fun main() {
val numericParam = environment.getProperty("app-conf.numeric-param", Int::class.java, 0)
val stringParam = environment.getProperty("app-conf.string-param", String::class.java, "")
val undefinedParam = environment.getProperty("app-conf.undefined-param", String::class.java, "defaultValue")
val structureParam1 = environment.getProperty("app-conf.structure-param.param1", String::class.java, "")
val structureParam2 = environment.getProperty("app-conf.structure-param.param2", String::class.java, "")
println("numericParam=$numericParam")
println("stringParam=$stringParam")
println("undefinedParam=$undefinedParam")
println("structureParam.param1=$structureParam1")
println("structureParam.param2=$structureParam2")
}
}
numericParam=10
stringParam=hogehoge
undefinedParam=defaultValue
structureParam.param1=hoge
structureParam.param2=fuga
getProperty()
の第一引数にキー、第二引数に取得する型のClass、第三引数にデフォルト値を渡します。
なおgetProperty()
メソッドはデフォルト値を省略した場合は戻り値がnullableになり、キーが未定義の場合nullが帰ります。
未定義の場合にエラーを発生させたいときはgetProperty()
の代わりにgetRequiredProperty()
を使用します。
// 未定義の場合エラーになる
val undefinedParam = environment.getRequiredProperty("app-conf.undefined-param", String::class.java)
ConfigurationProperties
@ConfigurationProperties
アノテーションを使用すると複数のパラメータをまとめて取得することができます。
@Component
class ConfigurationPropertiesComponent {
@Autowired
lateinit var appConfig: AppConfig
fun main() {
println("numericParam=${appConfig.numericParam}")
println("stringParam=${appConfig.stringParam}")
println("undefinedParam=${appConfig.undefinedParam}")
println("structureParam.param1=${appConfig.structureParam.param1}")
println("structureParam.param2=${appConfig.structureParam.param2}")
}
}
@Configuration
@ConfigurationProperties("app-conf")
class AppConfig {
var numericParam = 0
var stringParam = ""
var undefinedParam = "defaultValue"
val structureParam = StructureParam()
}
class StructureParam {
var param1 = ""
var param2 = ""
}
numericParam=10
stringParam=hogehoge
undefinedParam=defaultValue
structureParam.param1=hoge
structureParam.param2=fuga
パラメータを受け取るクラスに@ConfigurationProperties
アノテーションを付与します。
フィールドへはsetter経由で値が設定されるためval
は使用できません。(階層化されたプロパティを除く)
appConfig.structureParam.param1
、appConfig.structureParam.param2
のように階層構造をもったパラメータも取得できます。
ただし、パラメータを受け取るためのインスタンスは自動生成してくれないので、あらかじめインスタンスを生成しておく必要があります。(こちらはval
で定義できます)
また、パラメータ名とフィールド名は厳密に同じでなくてもある程度までいい感じに認識してくれます。
追記
Spring Boot 2.2系から@ConstructorBinding
が追加されたため、@ConfigurationProperties
でdata classが利用可能になりました。
参考 : Spring Boot 2.2系で@ConfigurationPropertiesを使う
@SpringBootApplication
// メインクラスに@ConfigurationPropertiesScanをつける必要があります
@ConfigurationPropertiesScan
class DemoApplication
// ...mainメソッド略...
@Component
class ConfigurationPropertiesComponent {
@Autowired
lateinit var appConfig: DataClassConfig
fun main() {
println(appConfig)
}
}
// @ConfigurationPropertiesに@ConstructorBindingを追加
@ConstructorBinding
@ConfigurationProperties("app-conf")
data class DataClassConfig(
val numericParam: Int,
val stringParam: String,
val undefinedParam: String = "defaultValue",
// 階層構造を持つパラメータも事前のインスタンス化は不要です
val structureParam: DataClassStructureParam
)
data class DataClassStructureParam(
val param1: String,
val param2: String
)
DataClassConfig(numericParam=10, stringParam=hogehoge, undefinedParam=defaultValue, structureParam=DataClassStructureParam(param1=hoge, param2=fuga))
まとめ
application.ymlから値を取得する3つの方法をkotlinで試してみました。
それぞれ一長一短あるので適切に使い分けて利用したいです。