はじめに
Springの設定周り(Config的なところ)について気になったので、リファレンス引いてメモしたってだけのやつです。
Spring Bootの設定値ってどうなってるの
Spring Bootを使っていると分かるけど、application.yml、システムプロパティ、環境変数などから取得してよしなに取ってきてくれる。
具体的にはこの順番でとってくるらしい。
https://spring.pleiades.io/spring-boot/docs/2.1.9.RELEASE/reference/html/boot-features-external-config.html
以下、引用。
1. ホームディレクトリの Devtools グローバル設定プロパティ(devtools がアクティブな場合は ~/.spring-boot-devtools.properties)。
2. テストに関する @TestPropertySource(Javadoc) アノテーション。
3. テストの properties 属性。 @SpringBootTest(Javadoc) およびアプリケーションの特定のスライスをテストするためのテストアノテーションで利用可能。
4. コマンドライン引数。
5. SPRING_APPLICATION_JSON のプロパティ(環境変数またはシステムプロパティに埋め込まれたインライン JSON)。
6. ServletConfig 初期化パラメーター。
7. ServletContext 初期化パラメーター。
8. java:comp/env からの JNDI 属性。
9. Java システムプロパティ(System.getProperties())。
10. OS 環境変数。
11. random.* のみにプロパティを持つ RandomValuePropertySource。
12. パッケージ化された jar 以外のプロファイル固有のアプリケーションプロパティ(application-{profile}.properties および YAML バリアント)。
13. jar(application-{profile}.properties および YAML バリアント)内にパッケージ化されたプロ- - ファイル固有のアプリケーションプロパティ。
14. パッケージ化された jar 以外のアプリケーションプロパティ(application.properties および YAML バリアント)。
15. jar 内にパッケージ化されたアプリケーションプロパティ(application.properties および YAML バリアント)。
16. @Configuration クラスの @PropertySource アノテーション。
17. デフォルトのプロパティ(SpringApplication.setDefaultProperties の設定により指定されます)。
ドキュメントを眺めていると、2.1.x系以降(2.2.xと2.3.x)はこの説明がまるごとどこかにいってしまっているけど、きっと優先順位は同じと思う。
これは12 Factor Appとかに書いてあるのを考慮出来てるのでまぁ良い設計なのだと思う。Goのviperとかもそんな感じだったし。
https://12factor.net/ja/config
開発とテスト用のものも含まれていて、実際に諸々の設定に使われるのは環境変数とapplication.properties、他に使うとしてコマンドライン引数とかあたりじゃないかと思う。
設定値の命名ってどうすればいいの
色々なところで設定出来て優先度があることはわかった。で、設定値のkey=valueのkeyの部分ってどういう命名にすれば良いんだっけ?となった。環境変数なら環境変数の命名規約はあるけど、それらの相互互換性とかどうなってるんだろうとかそういうの。
それを決めるのがRelaxed Bindingという仕様らしい。英語だとあれだけどゆるーく変数バインドしますって雑に訳せる。それっぽくかけばちゃんとバインディングしてくれるというもの。 Relaxed Bindingは @ConfigurationPropertiesのためのものらしい(org.springframework.boot.context.properties.ConfigurationProperties)。ConfigurationPropertiesはprefix.hoge-fuga.piyoみたいな感じ。設定ファイルや環境変数側はそれぞれに推奨されるもの or サポートされるものであれば色々なケースで大丈夫っぽい。設定ファイルならケバブ、キャメルなど使えそう。環境変数は大文字のスネークケース(詳細はリファレンス参照)。
しかもこれはSpring Bootの仕様の一部らしい。Springではないのか。そもそもapplication.ymlとか読んでるあたりってBoot側がやってくれてるということになるんだろうか。
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-relaxed-binding
https://spring.pleiades.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-relaxed-binding
@Valueについて
@Value(“xxxx”) というのはどういう命名規約で書けば良いのか、というのも気になった(org.springframework.beans.factory.annotation.Value)。
ドキュメントによると小文字のドットつなぎにすることが推奨されているとのことだった。それによってRelaxed Bindingと同じロジック適用されるので設定した変数の命名のゆらぎを吸収してくれるとのこと。
最近はSpring Bootチームが@Valueより@ConfigurationPropertiesを推奨していて、そもそもRelaxed Bindingも@ConfigurationProperties用のものだった。したがって@ValueはRelaxed Bindingサポート無しと過去バージョンではしていたようだが、 current (2020-09-17 12:58:07 UTC) では限定的サポート(Limited)になっている。
詳細はこの辺り。
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config-vs-value
過去のissue
https://github.com/spring-projects/spring-boot/issues/4413
書いてて思ったけど
リファレンスのcurrentバージョンを参照してると、数年経ったら見れなくなってるとかドキュメントの構成が変わってたりしたら面倒そうですね。
バージョン指定しとく方がいいんだろうか。。
まとめ
Spring Bootのこのあたりの仕様について調べてみた。
僕にとってはこれだけでも充分に複雑で(旧)J2EEのアンチテーゼとはなんやったんやーみたいになるけど、歴史的経緯もたくさんあると思うのでそれはそれで仕方ない(いろいろなところから設定値を読み込むのを見たときに、あぁ…歴史を感じる、となった)。というかEE仕様が複雑だと結局Springも引きずられる気がする。(たぶん)イマドキだとServletとかJNDIとか捨てれそうだけど、Javaの色々なものが後方互換バリバリ前提なので、切り捨てるわけにもいかないだろうなと。
便利なのには間違い無いので、ありがたく使わせてもらおうーという感じです。
0 件のコメント:
コメントを投稿