環境別の設定切り替え
Spring Boot を使用すると、異なる環境で同じアプリケーションコードを操作できるように、設定を外部化したり、切り替えたりすることができます。Java プロパティファイル、YAML ファイル、環境変数、コマンドライン引数など、さまざまな外部設定ソースを使用できます。
プロパティ値は、@Value
アノテーションを使用して直接 Bean に注入したり、Spring の Environment
抽象化を通じてアクセスしたり、@ConfigurationProperties
を通じて構造化オブジェクトにバインドしたりできます。
Spring Boot は、値を適切にオーバーライドできるように設計された、非常に特殊な PropertySource
順序を使用します。後のプロパティソースは、以前のもので定義された値をオーバーライドできます。ソースは次の順序で考慮されます。
デフォルトのプロパティ(
SpringApplication.setDefaultProperties
の設定により指定されます)。@Configuration
クラスの@PropertySource
(Javadoc) アノテーション。このようなプロパティソースは、アプリケーションコンテキストがリフレッシュされるまでEnvironment
に追加されないことに注意してください。これは、リフレッシュが始まる前に読み込まれるlogging.*
やspring.main.*
などの特定のプロパティを設定するには遅すぎます。構成データ(
application.properties
ファイルなど)。random.*
のみにプロパティを持つRandomValuePropertySource
。OS 環境変数。
Java システムプロパティ(
System.getProperties()
)。java:comp/env
からの JNDI 属性。ServletContext
初期化パラメーター。ServletConfig
初期化パラメーター。SPRING_APPLICATION_JSON
のプロパティ(環境変数またはシステムプロパティに埋め込まれたインライン JSON)。コマンドライン引数。
テストの
properties
属性。@SpringBootTest
(Javadoc) と、アプリケーションの特定のスライスをテストするためのテストアノテーションで使用できます。テスト内の
@DynamicPropertySource
(Javadoc) アノテーション。テストに関する
@TestPropertySource
(Javadoc) アノテーション。devtools がアクティブな場合、
$HOME/.config/spring-boot
ディレクトリの Devtools グローバル設定プロパティ。
構成データファイルは、次の順序で考慮されます。
jar(
application.properties
および YAML バリアント)内にパッケージ化されたアプリケーションプロパティ。jar(
application-{profile}.properties
および YAML バリアント)内にパッケージ化されたプロファイル固有のアプリケーションプロパティ。パッケージ化された jar 以外のアプリケーションプロパティ(
application.properties
および YAML バリアント)。パッケージ化された jar 以外のプロファイル固有のアプリケーションプロパティ(
application-{profile}.properties
および YAML バリアント)。
アプリケーション全体で 1 つの形式を使用することをお勧めします。.properties 形式と YAML 形式の両方の構成ファイルが同じ場所にある場合は、.properties が優先されます。 |
システムプロパティではなく環境変数を使用する場合、ほとんどのオペレーティングシステムはピリオドで区切られたキー名を許可しませんが、代わりにアンダースコアを使用できます(たとえば、spring.config.name の代わりに SPRING_CONFIG_NAME )。詳細については、環境変数からのバインディングを参照してください。 |
アプリケーションがサーブレットコンテナーまたはアプリケーションサーバーで実行されている場合は、環境変数やシステムプロパティの代わりに、または環境変数やシステムプロパティの代わりに、JNDI プロパティ(java:comp/env 内)またはサーブレットコンテキスト初期化パラメーターを使用できます。 |
具体例を提供するために、次の例に示すように、name
プロパティを使用する @Component
を開発するとします。
Java
Kotlin
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
@Value("${name}")
private String name;
// ...
}
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
@Component
class MyBean {
@Value("\${name}")
private val name: String? = null
// ...
}
アプリケーションのクラスパス(たとえば、jar 内)に、name
の適切なデフォルトのプロパティ値を提供する application.properties
ファイルを含めることができます。新しい環境で実行する場合、name
をオーバーライドする jar の外部で application.properties
ファイルを提供できます。1 回限りのテストでは、特定のコマンドラインスイッチ(たとえば java -jar app.jar --name="Spring"
)で起動できます。
env および configprops エンドポイントは、プロパティが特定の値を持つ理由を判断できます。これらの 2 つのエンドポイントを使用して、予期しないプロパティ値を診断できます。詳細については、本番対応機能セクションを参照してください。 |
コマンドラインプロパティへのアクセス
デフォルトでは、SpringApplication
はコマンドラインオプション引数(つまり、--server.port=9000
などの --
で始まる引数)を property
に変換し、Spring Environment
に追加します。前述のように、コマンドラインプロパティは常にファイルベースのプロパティソースよりも優先されます。
コマンドラインプロパティを Environment
に追加したくない場合は、SpringApplication.setAddCommandLineProperties(false)
を使用して無効にすることができます。
JSON アプリケーションのプロパティ
多くの場合、環境変数とシステムプロパティには制限があり、一部のプロパティ名は使用できません。これを支援するために、Spring Boot ではプロパティのブロックを単一の JSON 構造にエンコードできます。
アプリケーションが起動すると、spring.application.json
または SPRING_APPLICATION_JSON
プロパティが解析され、Environment
に追加されます。
例: SPRING_APPLICATION_JSON
プロパティは、環境変数として UN*X シェルのコマンドラインで指定できます。
$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar
上記の例では、Spring Environment
の my.name=test
になります。
同じ JSON をシステムプロパティとして提供することもできます。
$ java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar
または、コマンドライン引数を使用して JSON を提供することもできます。
$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'
従来のアプリケーションサーバーにデプロイする場合は、java:comp/env/spring.application.json
という名前の JNDI 変数を使用することもできます。
JSON からの null 値が結果のプロパティソースに追加されますが、PropertySourcesPropertyResolver は null プロパティを欠損値として扱います。これは、JSON が null 値を持つ低次のプロパティソースからのプロパティをオーバーライドできないことを意味します。 |
外部アプリケーションプロパティ
Spring Boot は、アプリケーションの起動時に、次の場所から application.properties
ファイルと application.yaml
ファイルを自動的に検索してロードします。
クラスパスから
クラスパスのルート
クラスパス
/config
パッケージ
カレントディレクトリから
現在のディレクトリ
現在のディレクトリの
config/
サブディレクトリconfig/
サブディレクトリの直接の子ディレクトリ
リストは優先順位で並べられます(下位の項目の値が上位の項目の値を上書きします)。ロードされたファイルのドキュメントは、PropertySources
として Spring Environment
に追加されます。
構成ファイル名として application
が気に入らない場合は、spring.config.name
環境プロパティを指定して別のファイル名に切り替えることができます。例: myproject.properties
および myproject.yaml
ファイルを検索するには、次のようにアプリケーションを実行できます。
$ java -jar myproject.jar --spring.config.name=myproject
spring.config.location
環境プロパティを使用して、明示的な場所を参照することもできます。このプロパティは、チェックする 1 つ以上の場所のコンマ区切りリストを受け入れます。
次の例は、2 つの異なるファイルを指定する方法を示しています。
$ java -jar myproject.jar --spring.config.location=\
optional:classpath:/default.properties,\
optional:classpath:/override.properties
場所がオプションであり、存在しなくてもかまわない場合は、プレフィックス optional: を使用します。 |
spring.config.name 、spring.config.location 、spring.config.additional-location は、ロードする必要のあるファイルを決定するために非常に早い段階で使用されます。これらは、環境プロパティ(通常、OS 環境変数、システムプロパティ、コマンドライン引数)として定義する必要があります。 |
spring.config.location
に(ファイルではなく)ディレクトリが含まれている場合、/
で終わる必要があります。実行時に、ロードされる前に spring.config.name
から生成された名前が追加されます。spring.config.location
で指定されたファイルは直接インポートされます。
ディレクトリとファイルの場所の両方の値も展開され、プロファイル固有のファイルをチェックします。例: classpath:myconfig.properties の spring.config.location がある場合は、適切な classpath:myconfig-<profile>.properties ファイルもロードされていることがわかります。 |
ほとんどの場合、追加する各 spring.config.location
アイテムは単一のファイルまたはディレクトリを参照します。場所は定義された順序で処理され、後のものは前のものの値を上書きできます。
複雑な場所の設定があり、プロファイル固有の構成ファイルを使用する場合は、Spring Boot がグループ化方法を認識できるように、さらにヒントを提供する必要がある場合があります。場所グループとは、すべて同じレベルと見なされる場所のコレクションです。たとえば、すべてのクラスパスの場所をグループ化し、次にすべての外部の場所をグループ化したい場合があります。場所グループ内の項目は、;
で区切る必要があります。詳細については、プロファイル固有のファイルセクションの例を参照してください。
spring.config.location
を使用して構成された場所は、デフォルトの場所を置き換えます。例: spring.config.location
が値 optional:classpath:/custom-config/,optional:file:./custom-config/
で構成されている場合、考慮される場所の完全なセットは次のとおりです。
optional:classpath:custom-config/
optional:file:./custom-config/
場所を置き換えるのではなく、場所を追加したい場合は、spring.config.additional-location
を使用できます。追加の場所からロードされたプロパティは、デフォルトの場所のプロパティを上書きできます。例: spring.config.additional-location
が値 optional:classpath:/custom-config/,optional:file:./custom-config/
で構成されている場合、考慮される場所の完全なセットは次のとおりです。
optional:classpath:/;optional:classpath:/config/
optional:file:./;optional:file:./config/;optional:file:./config/*/
optional:classpath:custom-config/
optional:file:./custom-config/
この検索順序により、ある構成ファイルでデフォルト値を指定し、別の構成ファイルでそれらの値を選択的にオーバーライドできます。デフォルトの場所の 1 つで、application.properties
(または spring.config.name
で選択した他のベース名)でアプリケーションのデフォルト値を提供できます。これらのデフォルト値は、カスタムロケーションのいずれかにある別のファイルで実行時にオーバーライドできます。
オプションの場所
デフォルトでは、指定された構成データの場所が存在しない場合、Spring Boot は ConfigDataLocationNotFoundException
をスローし、アプリケーションは起動しません。
場所を指定したいが、常に存在していなくてもかまわない場合は、optional:
プレフィックスを使用できます。このプレフィックスは、spring.config.location
プロパティと spring.config.additional-location
プロパティ、および spring.config.import
宣言で使用できます。
例: optional:file:./myconfig.properties
の spring.config.import
値を使用すると、myconfig.properties
ファイルが欠落している場合でもアプリケーションを起動できます。
すべての ConfigDataLocationNotFoundExceptions
を無視して、常にアプリケーションを起動し続ける場合は、spring.config.on-not-found
プロパティを使用できます。SpringApplication.setDefaultProperties(…)
を使用するか、システム / 環境変数を使用して、値を ignore
に設定します。
ワイルドカードの場所
構成ファイルの場所に最後のパスセグメントの *
文字が含まれている場合、ワイルドカードの場所と見なされます。構成がロードされるとワイルドカードが展開されるため、即時サブディレクトリもチェックされます。ワイルドカードの場所は、構成プロパティのソースが複数ある場合の Kubernetes などの環境で特に役立ちます。
例: Redis 構成と MySQL 構成がある場合は、これら 2 つの構成を別々に保持し、両方が application.properties
ファイルに存在する必要がある場合があります。これにより、/config/redis/application.properties
や /config/mysql/application.properties
などの異なる場所に 2 つの別々の application.properties
ファイルがマウントされる可能性があります。このような場合、ワイルドカードの場所が config/*/
の場合、両方のファイルが処理されます。
デフォルトでは、Spring Boot はデフォルトの検索場所に config/*/
を含みます。これは、jar の外部にある /config
ディレクトリのすべてのサブディレクトリが検索されることを意味します。
spring.config.location
および spring.config.additional-location
プロパティを使用して、ワイルドカードの場所を自分で使用できます。
ワイルドカードの場所には、* が 1 つだけ含まれ、ディレクトリである検索場所の場合は */ で終わり、ファイルである検索場所の場合は */<filename> で終わる必要があります。ワイルドカードを使用した場所は、ファイル名の絶対パスに基づいてアルファベット順にソートされます。 |
ワイルドカードの場所は、外部ディレクトリでのみ機能します。classpath: の場所ではワイルドカードを使用できません。 |
プロファイル固有のファイル
application
プロパティファイルだけでなく、Spring Boot は、命名規則 application-{profile}
を使用してプロファイル固有のファイルをロードしようとします。例: アプリケーションが prod
という名前のプロファイルをアクティブ化し、YAML ファイルを使用する場合、application.yaml
と application-prod.yaml
の両方が考慮されます。
プロファイル固有のプロパティは、標準の application.properties
と同じ場所から読み込まれ、プロファイル固有のファイルは常に非特定のファイルを上書きします。複数のプロファイルが指定されている場合は、ラストウィン戦略が適用されます。例: プロファイル prod,live
が spring.profiles.active
プロパティで指定されている場合、application-prod.properties
の値は application-live.properties
の値で上書きできます。
ラストウィン戦略は、ロケーショングループレベルで適用されます。 例: 上記の /cfg application-live.properties /ext application-live.properties application-prod.properties
代わりに
|
Environment
には、アクティブなプロファイルが設定されていない場合に使用される一連のデフォルトプロファイル(デフォルトでは [default]
)があります。つまり、プロファイルが明示的にアクティブ化されていない場合、application-default
のプロパティが考慮されます。
プロパティファイルは一度だけロードされます。プロファイル固有のプロパティファイルをすでに直接インポートしている場合は、2 回目にインポートされることはありません。 |
追加データのインポート
アプリケーションプロパティは、spring.config.import
プロパティを使用して、他の場所からさらに構成データをインポートできます。インポートは、検出されたときに処理され、インポートを宣言するドキュメントのすぐ下に挿入された追加のドキュメントとして扱われます。
例: クラスパス application.properties
ファイルに次のものがある場合があります。
プロパティ
YAML
spring.application.name=myapp
spring.config.import=optional:file:./dev.properties
spring:
application:
name: "myapp"
config:
import: "optional:file:./dev.properties"
これにより、現在のディレクトリに dev.properties
ファイルがインポートされます(そのようなファイルが存在する場合)。インポートされた dev.properties
からの値は、インポートをトリガーしたファイルよりも優先されます。上記の例では、dev.properties
は spring.application.name
を別の値に再定義できます。
インポートは、宣言された回数に関係なく、一度だけインポートされます。インポートが properties/yaml ファイル内の単一のドキュメント内で定義される順序は重要ではありません。たとえば、以下の 2 つの例では同じ結果が得られます。
プロパティ
YAML
spring.config.import=my.properties
my.property=value
spring:
config:
import: "my.properties"
my:
property: "value"
プロパティ
YAML
my.property=value
spring.config.import=my.properties
my:
property: "value"
spring:
config:
import: "my.properties"
上記の両方の例で、my.properties
ファイルの値は、インポートをトリガーしたファイルよりも優先されます。
1 つの spring.config.import
キーで複数の場所を指定できます。場所は、定義された順序で処理され、後のインポートが優先されます。
必要に応じて、プロファイル固有のバリアントもインポートの対象と見なされます。上記の例では、my.properties と my-<profile>.properties バリアントの両方をインポートします。 |
Spring Boot には、さまざまな場所のアドレスをサポートできるプラグ可能な API が含まれています。デフォルトでは、Java プロパティ、YAML、構成ツリーをインポートできます。 サードパーティの jar は、追加のテクノロジのサポートを提供できます (ファイルがローカルである必要はありません)。例: 構成データが Consul、Apache ZooKeeper、Netflix Archaius などの外部ストアから取得されることが考えられます。 独自の場所をサポートする場合は、 |
拡張機能のないファイルのインポート
一部のクラウドプラットフォームは、ボリュームにマウントされたファイルにファイル拡張子を追加できません。これらの拡張子のないファイルをインポートするには、Spring Boot にヒントを与えて、ロードする方法を認識させる必要があります。これを行うには、角括弧に拡張ヒントを配置します。
例: yaml としてインポートしたい /etc/config/myconfig
ファイルがあるとします。以下を使用して、application.properties
からインポートできます。
プロパティ
YAML
spring.config.import=file:/etc/config/myconfig[.yaml]
spring:
config:
import: "file:/etc/config/myconfig[.yaml]"
構成ツリーの使用
クラウドプラットフォーム(Kubernetes など)でアプリケーションを実行する場合、プラットフォームが提供する構成値を読み取る必要があることがよくあります。このような目的で環境変数を使用することは珍しくありませんが、特に値を秘密にしておくことになっている場合、これには欠点があります。
環境変数の代わりに、多くのクラウドプラットフォームで、構成をマウントされたデータボリュームにマッピングできるようになりました。例: Kubernetes は ConfigMaps
(英語) と Secrets
(英語) の両方をボリュームマウントできます。
使用できる一般的なボリュームマウントパターンは 2 つあります。
1 つのファイルには、プロパティの完全なセットが含まれています(通常は YAML として記述されます)。
複数のファイルがディレクトリツリーに書き込まれ、ファイル名が「キー」になり、内容が「値」になります。
最初のケースでは、上記のように spring.config.import
を使用して YAML またはプロパティファイルを直接インポートできます。2 番目のケースでは、configtree:
プレフィックスを使用して、すべてのファイルをプロパティとして公開する必要があることを Spring Boot が認識できるようにする必要があります。
例として、Kubernetes が次のボリュームをマウントしたと想像してみましょう。
etc/
config/
myapp/
username
password
username
ファイルの内容は構成値になり、password
の内容は秘密になります。
これらのプロパティをインポートするには、application.properties
または application.yaml
ファイルに以下を追加します。
プロパティ
YAML
spring.config.import=optional:configtree:/etc/config/
spring:
config:
import: "optional:configtree:/etc/config/"
その後、通常の方法で Environment
から myapp.username
および myapp.password
プロパティにアクセスまたは挿入できます。
構成ツリーのフォルダーとファイルの名前がプロパティ名を形成します。上の例では、username および password としてプロパティにアクセスするには、spring.config.import を optional:configtree:/etc/config/myapp に設定します。 |
ドット表記のファイル名も正しくマッピングされます。例: 上記の例では、/etc/config の myapp.username という名前のファイルは、Environment の myapp.username プロパティになります。 |
構成ツリーの値は、予想される内容に応じて、文字列 String 型と byte[] 型の両方にバインドできます。 |
同じ親フォルダーからインポートする複数の構成ツリーがある場合は、ワイルドカードショートカットを使用できます。/*/
で終わる configtree:
の場所は、すべての直接の子を構成ツリーとしてインポートします。非ワイルドカードインポートと同様に、各構成ツリーのフォルダーとファイルの名前がプロパティ名を形成します。
例: 次のボリュームがある場合:
etc/
config/
dbconfig/
db/
username
password
mqconfig/
mq/
username
password
インポート場所として configtree:/etc/config/*/
を使用できます。
プロパティ
YAML
spring.config.import=optional:configtree:/etc/config/*/
spring:
config:
import: "optional:configtree:/etc/config/*/"
これにより、db.username
、db.password
、mq.username
、mq.password
プロパティが追加されます。
ワイルドカードを使用してロードされたディレクトリは、アルファベット順にソートされます。別のオーダーが必要な場合は、各場所を個別のインポートとしてリストする必要があります |
構成ツリーは、Docker シークレットにも使用できます。Docker スウォームサービスにシークレットへのアクセスが許可されると、シークレットはコンテナーにマウントされます。例: db.password
という名前のシークレットが /run/secrets/
の場所にマウントされている場合、以下を使用して db.password
を Spring 環境で使用可能にすることができます。
プロパティ
YAML
spring.config.import=optional:configtree:/run/secrets/
spring:
config:
import: "optional:configtree:/run/secrets/"
プロパティプレースホルダー
application.properties
および application.yaml
の値は、使用時に既存の Environment
でフィルタリングされるため、以前に定義された値(たとえば、システムプロパティまたは環境変数から)を参照することができます。標準の ${name}
プロパティ - プレースホルダー構文は、値内のどこでも使用できます。プロパティプレースホルダーは、:
を使用してデフォルト値を指定し、デフォルト値をプロパティ名から分離することもできます(例: ${name:default}
)。
次の例では、デフォルトがある場合とない場合のプレースホルダーの使用を示しています。
プロパティ
YAML
app.name=MyApp
app.description=${app.name} is a Spring Boot application written by ${username:Unknown}
app:
name: "MyApp"
description: "${app.name} is a Spring Boot application written by ${username:Unknown}"
username
プロパティが他の場所に設定されていないと仮定すると、app.description
の値は MyApp is a Spring Boot application written by Unknown
になります。
プレースホルダー内のプロパティ名は、常に正規形(小文字のみを使用する kebab-case)を使用して参照する必要があります。これにより、Spring Boot は、 例: |
この手法を使用して、既存の Spring Boot プロパティの「短縮」バリアントを作成することもできます。詳細については、「使い方 ガイド」の「短い」コマンドライン引数を使用するセクションを参照してください。 |
マルチドキュメントファイルの操作
Spring Boot を使用すると、単一の物理ファイルを複数の論理ドキュメントに分割し、それぞれを個別に追加できます。ドキュメントは上から下に順番に処理されます。後のドキュメントは、前のドキュメントで定義されたプロパティを上書きできます。
application.yaml
ファイルの場合、標準の YAML マルチドキュメント構文が使用されます。3 つの連続するハイフンは、1 つのドキュメントの終わりと、次のドキュメントの始まりを表します。
例: 次のファイルには 2 つの論理ドキュメントがあります。
spring:
application:
name: "MyApp"
---
spring:
application:
name: "MyCloudApp"
config:
activate:
on-cloud-platform: "kubernetes"
application.properties
ファイルの場合、特別な #---
または !---
コメントを使用してドキュメントの分割をマークします。
spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes
プロパティファイルの区切り記号には、先頭に空白を入れてはならず、正確に 3 つのハイフン文字を含める必要があります。セパレータの直前と直後の行は、同じコメントプレフィックスであってはなりません。 |
マルチドキュメントプロパティファイルは、spring.config.activate.on-profile などのアクティベーションプロパティと組み合わせて使用されることがよくあります。詳細については、次のセクションを参照してください。 |
マルチドキュメントプロパティファイルは、@PropertySource または @TestPropertySource アノテーションを使用してロードすることはできません。 |
アクティベーションプロパティ
特定の条件が満たされた場合にのみ、特定のプロパティのセットをアクティブ化すると便利な場合があります。例: 特定のプロファイルがアクティブな場合にのみ関連するプロパティがある場合があります。
spring.config.activate.*
を使用して、プロパティドキュメントを条件付きでアクティブ化できます。
次のアクティベーションプロパティを使用できます。
プロパティ | メモ |
---|---|
| ドキュメントをアクティブにするために一致する必要があるプロファイル式。 |
| ドキュメントをアクティブにするために検出する必要がある |
例: 以下は、2 番目のドキュメントが Kubernetes で実行されている場合、および "prod" プロファイルまたは "staging" プロファイルのいずれかがアクティブである場合にのみアクティブになることを指定します。
プロパティ
YAML
myprop=always-set
#---
spring.config.activate.on-cloud-platform=kubernetes
spring.config.activate.on-profile=prod | staging
myotherprop=sometimes-set
myprop:
"always-set"
---
spring:
config:
activate:
on-cloud-platform: "kubernetes"
on-profile: "prod | staging"
myotherprop: "sometimes-set"
暗号化プロパティ
Spring Boot は、プロパティ値を暗号化するための組み込みサポートを提供しませんが、Spring Environment
に含まれる値を変更するために必要なフックポイントを提供します。EnvironmentPostProcessor
インターフェースを使用すると、アプリケーションの開始前に Environment
を操作できます。詳細については、開始する前に環境または ApplicationContext をカスタマイズするを参照してください。
クレデンシャルとパスワードを安全に保存する方法が必要な場合、Spring Cloud Vault (英語) プロジェクトは、外部化された設定を HashiCorp Vault (英語) に保存するためのサポートを提供します。
YAML の操作
YAML (英語) は JSON のスーパーセットであるため、階層構成データを指定するための便利な形式です。SpringApplication
クラスは、クラスパスに SnakeYAML [GitHub] (英語) ライブラリがある場合は常に、プロパティの代替として YAML を自動的にサポートします。
スターターを使用する場合、SnakeYAML は spring-boot-starter によって自動的に提供されます。 |
YAML をプロパティにマッピングする
YAML ドキュメントは、階層形式から Spring Environment
で使用できるフラットな構造に変換する必要があります。例: 次の YAML ドキュメントを検討してください:
environments:
dev:
url: "https://dev.example.com"
name: "Developer Setup"
prod:
url: "https://another.example.com"
name: "My Cool App"
Environment
からこれらのプロパティにアクセスするために、これらは次のようにフラット化されます。
environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App
同様に、YAML リストもフラット化する必要があります。これらは、[index]
デリファレンスを使用したプロパティキーとして表されます。例: 次の YAML を検討してください:
my:
servers:
- "dev.example.com"
- "another.example.com"
前述の例は、次のプロパティに変換されます。
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
[index] 表記を使用するプロパティは、Spring Boot の Binder クラスを使用して Java List または Set オブジェクトにバインドできます。詳細については、以下の型安全な構成プロパティセクションを参照してください。 |
YAML ファイルは、@PropertySource または @TestPropertySource アノテーションを使用してロードすることはできません。そのように値をロードする必要がある場合は、プロパティファイルを使用する必要があります。 |
ランダム値の構成
RandomValuePropertySource
は、ランダムな値を挿入するのに便利です(たとえば、シークレットやテストケースに)。次の例に示すように、整数、long、uuid、文字列を生成できます。
プロパティ
YAML
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number-less-than-ten=${random.int(10)}
my.number-in-range=${random.int[1024,65536]}
my:
secret: "${random.value}"
number: "${random.int}"
bignumber: "${random.long}"
uuid: "${random.uuid}"
number-less-than-ten: "${random.int(10)}"
number-in-range: "${random.int[1024,65536]}"
random.int*
構文は OPEN value (,max) CLOSE
です。OPEN,CLOSE
は任意の文字で、value,max
は整数です。max
が指定されている場合、value
が最小値で、max
が最大値(排他的)です。
システム環境プロパティの構成
Spring Boot は、環境プロパティのプレフィックスの設定をサポートしています。これは、システム環境が異なる構成要件を持つ複数の Spring Boot アプリケーションによって共有されている場合に役立ちます。システム環境プロパティのプレフィックスは、SpringApplication
で直接設定できます。
例: プレフィックスを input
に設定すると、remote.timeout
などのプロパティもシステム環境で input.remote.timeout
として解決されます。
型安全な構成プロパティ
@Value("${property}")
アノテーションを使用して構成プロパティを注入することは、特に複数のプロパティを使用している場合、またはデータが本質的に階層的である場合には、面倒な場合があります。Spring Boot は、強く型付けされた Bean がアプリケーションの構成を管理および検証できるようにするプロパティを操作する代替方法を提供します。
@Value と型安全構成プロパティの違いも参照してください。 |
JavaBean プロパティのバインディング
次の例に示すように、標準 JavaBean プロパティを宣言する Bean をバインドすることができます。
Java
Kotlin
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my.service")
public class MyProperties {
private boolean enabled;
private InetAddress remoteAddress;
private final Security security = new Security();
// getters / setters...
public boolean isEnabled() {
return this.enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public InetAddress getRemoteAddress() {
return this.remoteAddress;
}
public void setRemoteAddress(InetAddress remoteAddress) {
this.remoteAddress = remoteAddress;
}
public Security getSecurity() {
return this.security;
}
public static class Security {
private String username;
private String password;
private List<String> roles = new ArrayList<>(Collections.singleton("USER"));
// getters / setters...
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public List<String> getRoles() {
return this.roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
import java.net.InetAddress
@ConfigurationProperties("my.service")
class MyProperties {
var isEnabled = false
var remoteAddress: InetAddress? = null
val security = Security()
class Security {
var username: String? = null
var password: String? = null
var roles: List<String> = ArrayList(setOf("USER"))
}
}
前述の POJO は、次のプロパティを定義します。
my.service.enabled
、デフォルトではfalse
の値。String
から強制変換できる型のmy.service.remote-address
。my.service.security.username
、ネストされた「セキュリティ」オブジェクト。その名前はプロパティの名前によって決定されます。特に、その型はまったく使用されておらず、SecurityProperties
である可能性があります。my.service.security.password
.my.service.security.roles
。デフォルトはUSER
であるString
のコレクションです。
プロパティファイル、YAML ファイル、環境変数、その他のメカニズムを介して構成された Spring Boot で使用可能な @ConfigurationProperties クラスにマップされるプロパティは、パブリック API ですが、クラス自体のアクセサー(getter/setter)を直接使用するためのものではありません。 |
このような配置は、デフォルトの空のコンストラクターに依存しており、getter と setter は通常必須です。これは、バインディングが Spring MVC の場合と同様に、標準の Java Bean プロパティ記述子を介して行われるためです。setter は、次の場合に省略できます。
プロジェクト Lombok を使用して、getter と setter を自動的に追加する人もいます。Lombok はオブジェクトをインスタンス化するためにコンテナーによって自動的に使用されるため、そのような型の特定のコンストラクターを生成しないように注意してください。 最後に、標準の Java Bean プロパティのみが考慮され、静的プロパティのバインドはサポートされていません。 |
コンストラクターのバインド
前のセクションの例は、次の例に示すように不変の方法で書き換えることができます。
Java
Kotlin
import java.net.InetAddress;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
@ConfigurationProperties("my.service")
public class MyProperties {
// fields...
private final boolean enabled;
private final InetAddress remoteAddress;
private final Security security;
public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
// getters...
public boolean isEnabled() {
return this.enabled;
}
public InetAddress getRemoteAddress() {
return this.remoteAddress;
}
public Security getSecurity() {
return this.security;
}
public static class Security {
// fields...
private final String username;
private final String password;
private final List<String> roles;
public Security(String username, String password, @DefaultValue("USER") List<String> roles) {
this.username = username;
this.password = password;
this.roles = roles;
}
// getters...
public String getUsername() {
return this.username;
}
public String getPassword() {
return this.password;
}
public List<String> getRoles() {
return this.roles;
}
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import java.net.InetAddress
@ConfigurationProperties("my.service")
class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
val security: Security) {
class Security(val username: String, val password: String,
@param:DefaultValue("USER") val roles: List<String>)
}
この設定では、単一のパラメーター化されたコンストラクターが存在するということは、コンストラクターバインディングを使用する必要があることを意味します。つまり、バインダーは、バインドするパラメーターを持つコンストラクターを見つけます。クラスに複数のコンストラクターがある場合は、@ConstructorBinding
アノテーションを使用して、コンストラクターバインディングに使用するコンストラクターを指定できます。単一のパラメーター化されたコンストラクターを持つクラスのコンストラクターバインディングをオプトアウトするには、コンストラクターに @Autowired
アノテーションを付ける、または private
にする必要があります。コンストラクターバインディングはレコードで使用できます。レコードに複数のコンストラクターがない限り、@ConstructorBinding
を使用する必要はありません。
コンストラクターにバインドされたクラス(上記の例の Security
など)のネストされたメンバーも、コンストラクターを介してバインドされます。
デフォルト値は、コンストラクターパラメーターおよびレコードコンポーネントで @DefaultValue
を使用して指定できます。変換サービスは、アノテーションの String
値を欠落しているプロパティのターゲット型に強制変換するために適用されます。
前の例を参照すると、プロパティが Security
にバインドされていない場合、MyProperties
インスタンスには security
の null
値が含まれます。プロパティがバインドされていない場合でも Security
の null 以外のインスタンスを含めるには (Kotlin を使用する場合、Security
の username
および password
パラメーターはデフォルト値を持たないため、null 可能として宣言する必要があります)、空の @DefaultValue
アノテーション:
Java
Kotlin
public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {
this.enabled = enabled;
this.remoteAddress = remoteAddress;
this.security = security;
}
class MyProperties(val enabled: Boolean, val remoteAddress: InetAddress,
@DefaultValue val security: Security) {
class Security(val username: String?, val password: String?,
@param:DefaultValue("USER") val roles: List<String>)
}
コンストラクターバインディングを使用するには、@EnableConfigurationProperties または構成プロパティスキャンを使用してクラスを有効にする必要があります。通常の Spring メカニズムによって作成された Bean でコンストラクターバインディングを使用することはできません。(たとえば、@Component Bean、@Bean メソッドを使用して作成された Bean、または @Import を使用してロードされた Bean ) |
コンストラクターバインディングを使用するには、クラスを -parameters でコンパイルする必要があります。これは、Spring Boot の Gradle プラグインを使用する場合、または Maven と spring-boot-starter-parent を使用する場合に自動的に行われます。 |
java.util.Optional と @ConfigurationProperties の併用は、主に戻り値の型としての使用を目的としているためお勧めしません。そのため、構成プロパティの注入には適していません。他の型のプロパティとの一貫性を保つために、Optional プロパティを宣言し、それに値がない場合、空の Optional ではなく null がバインドされます。 |
my.service.import などのプロパティ名に予約キーワードを使用するには、コンストラクターパラメーターで @Name アノテーションを使用します。 |
@ConfigurationProperties アノテーション付き型の有効化
Spring Boot は、@ConfigurationProperties
型をバインドし、Bean として登録するためのインフラストラクチャを提供します。クラスごとに構成プロパティを有効にするか、コンポーネントスキャンと同様に機能する構成プロパティスキャンを有効にすることができます。
@ConfigurationProperties
アノテーションが付けられたクラスは、たとえば、独自の自動構成を開発している場合や、条件付きで有効にしたい場合など、スキャンに適さない場合があります。これらの場合、@EnableConfigurationProperties
アノテーションを使用して処理する型のリストを指定します。これは、次の例に示すように、@Configuration
クラスで実行できます。
Java
Kotlin
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {
}
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties::class)
class MyConfiguration
Java
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("some.properties")
public class SomeProperties {
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("some.properties")
class SomeProperties
構成プロパティのスキャンを使用するには、@ConfigurationPropertiesScan
アノテーションをアプリケーションに追加します。通常、@SpringBootApplication
アノテーションが付けられたメインアプリケーションクラスに追加されますが、任意の @Configuration
クラスに追加できます。デフォルトでは、アノテーションを宣言するクラスのパッケージからスキャンが行われます。スキャンする特定のパッケージを定義する場合は、次の例に示すように定義できます。
Java
Kotlin
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {
}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationPropertiesScan
@SpringBootApplication
@ConfigurationPropertiesScan("com.example.app", "com.example.another")
class MyApplication
|
@ConfigurationProperties
は環境のみを扱い、特にコンテキストから他の Bean を注入しないことをお勧めします。コーナーケースの場合、setter インジェクションを使用するか、フレームワークによって提供される *Aware
インターフェースのいずれか(Environment
へのアクセスが必要な場合は EnvironmentAware
など)を使用できます。それでもコンストラクターを使用して他の Bean を注入する場合は、構成プロパティ Bean に @Component
のアノテーションを付け、JavaBean ベースのプロパティバインディングを使用する必要があります。
@ConfigurationProperties アノテーション付き型の使用
このスタイルの構成は、次の例に示すように、SpringApplication
外部 YAML 構成で特にうまく機能します。
my:
service:
remote-address: 192.168.1.1
security:
username: "admin"
roles:
- "USER"
- "ADMIN"
@ConfigurationProperties
Bean を使用するには、次の例に示すように、他の Bean と同じ方法で注入できます。
Java
Kotlin
import org.springframework.stereotype.Service;
@Service
public class MyService {
private final MyProperties properties;
public MyService(MyProperties properties) {
this.properties = properties;
}
public void openConnection() {
Server server = new Server(this.properties.getRemoteAddress());
server.start();
// ...
}
// ...
}
import org.springframework.stereotype.Service
@Service
class MyService(val properties: MyProperties) {
fun openConnection() {
val server = Server(properties.remoteAddress)
server.start()
// ...
}
// ...
}
@ConfigurationProperties を使用すると、独自のキーの自動補完を提供するために IDE で使用できるメタデータファイルを生成することもできます。詳細については付録を参照してください。 |
サードパーティの構成
@ConfigurationProperties
を使用してクラスにアノテーションを付けるだけでなく、パブリック @Bean
メソッドでも使用できます。これは、コントロール外のサードパーティコンポーネントにプロパティをバインドする場合に特に役立ちます。
Environment
プロパティから Bean を構成するには、次の例に示すように、@ConfigurationProperties
を Bean 登録に追加します。
Java
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class ThirdPartyConfiguration {
@Bean
@ConfigurationProperties(prefix = "another")
public AnotherComponent anotherComponent() {
return new AnotherComponent();
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration(proxyBeanMethods = false)
class ThirdPartyConfiguration {
@Bean
@ConfigurationProperties(prefix = "another")
fun anotherComponent(): AnotherComponent = AnotherComponent()
}
another
プレフィックスで定義された JavaBean プロパティは、前述の SomeProperties
の例と同様の方法で、その AnotherComponent
Bean にマッピングされます。
緩いバインディング
Spring Boot は、Environment
プロパティを @ConfigurationProperties
Bean にバインドするためにいくつかの緩和されたルールを使用しているため、Environment
プロパティ名と Bean プロパティ名が完全に一致する必要はありません。これが役立つ一般的な例には、ダッシュで区切られた環境プロパティ(たとえば、context-path
が contextPath
にバインド)、大文字の環境プロパティ(たとえば、PORT
が port
にバインド)があります。
例として、次の @ConfigurationProperties
クラスを検討してください。
Java
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties(prefix = "my.main-project.person")
class MyPersonProperties {
var firstName: String? = null
}
上記のコードでは、次のプロパティ名をすべて使用できます。
プロパティ | メモ |
---|---|
| Kebab ケース。 |
| 標準のキャメルケースの構文。 |
| アンダースコア表記。 |
| システム環境変数を使用する場合に推奨される大文字形式。 |
アノテーションの prefix 値はケバブの場合(小文字で、my.main-project.person などの - で区切られている)でなければなりません。 |
プロパティソース | シンプル | リスト |
---|---|---|
プロパティファイル | キャメルケース、ケバブケース、アンダースコア表記 |
|
YAML ファイル | キャメルケース、ケバブケース、アンダースコア表記 | 標準の YAML リスト構文またはコンマ区切り値 |
環境変数 | 区切り文字としてアンダースコアを使用した大文字の形式(環境変数からのバインディングを参照)。 | アンダースコアで囲まれた数値 ( 環境変数からのバインディングを参照してください) |
システムプロパティ | キャメルケース、ケバブケース、アンダースコア表記 |
|
可能な場合、プロパティは my.person.first-name=Rod などの小文字のケバブ形式で保存することをお勧めします。 |
マップのバインド
Map
プロパティにバインドする場合、元の key
値が保持されるように、特別な括弧表記を使用する必要がある場合があります。キーが []
で囲まれていない場合、英数字、-
、.
以外の文字はすべて削除されます。
例: 次のプロパティを Map<String,String>
にバインドすることを検討してください。
プロパティ
YAML
my.map[/key1]=value1
my.map[/key2]=value2
my.map./key3=value3
my:
map:
"[/key1]": "value1"
"[/key2]": "value2"
"/key3": "value3"
YAML ファイルの場合、キーを適切に解析するには、括弧を引用符で囲む必要があります。 |
上記のプロパティは、マップ内のキーとして /key1
、/key2
、key3
を使用して Map
にバインドされます。スラッシュは角括弧で囲まれていなかったため、key3
から削除されました。
スカラー値にバインドする場合、.
を含むキーを []
で囲む必要はありません。スカラー値には、Object
を除く java.lang
パッケージの列挙型とすべての型が含まれます。a.b=c
を Map<String, String>
にバインドすると、キーに .
が保持され、エントリ {"a.b"="c"}
のマップが返されます。その他の型では、key
に .
が含まれている場合は、括弧表記を使用する必要があります。例: a.b=c
を Map<String, Object>
にバインドすると、エントリ {"a"={"b"="c"}}
のマップが返されますが、[a.b]=c
はエントリ {"a.b"="c"}
のマップが返されます。
環境変数からのバインディング
ほとんどのオペレーティングシステムでは、環境変数に使用できる名前に関する厳格なルールが適用されます。例: Linux シェル変数には、文字(a
から z
または A
から Z
)、数字(0
から 9
)または下線文字(_
)のみを含めることができます。慣例により、Unix シェル変数も大文字で名前が付けられます。
Spring Boot の緩いバインディングルールは、可能な限り、これらの命名制限と互換性を持つように設計されています。
正規形式のプロパティ名を環境変数名に変換するには、次のルールに従います。
ドット(
.
)をアンダースコア(_
)に置き換えます。ダッシュ(
-
)をすべて削除します。大文字に変換します。
例: 構成プロパティ spring.main.log-startup-info
は SPRING_MAIN_LOGSTARTUPINFO
という名前の環境変数になります。
環境変数は、オブジェクトリストにバインドするときにも使用できます。List
にバインドするには、変数名で要素番号をアンダースコアで囲む必要があります。例: 構成プロパティ my.service[0].other
は、MY_SERVICE_0_OTHER
という名前の環境変数を使用します。
環境変数からのバインディングのサポートは、systemEnvironment
プロパティソースと、名前が -systemEnvironment
で終わる追加のプロパティソースに適用されます。
環境変数からのマップのバインド
Spring Boot が環境変数をプロパティクラスにバインドする場合、バインドする前に環境変数名を小文字にします。ほとんどの場合、この詳細は重要ではありませんが、Map
プロパティにバインドする場合は例外です。
Map
のキーは、次の例に示すように常に小文字です。
Java
Kotlin
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.props")
public class MyMapsProperties {
private final Map<String, String> values = new HashMap<>();
public Map<String, String> getValues() {
return this.values;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties(prefix = "my.props")
class MyMapsProperties {
val values: Map<String, String> = HashMap()
}
MY_PROPS_VALUES_KEY=value
を設定すると、values
Map
に {"key"="value"}
エントリが含まれます。
環境変数名のみが小文字化され、値は小文字化されません。MY_PROPS_VALUES_KEY=VALUE
を設定すると、values
Map
に {"key"="VALUE"}
エントリが含まれます。
複合型のマージ
リストが複数の場所で構成されている場合、オーバーライドはリスト全体を置き換えることで機能します。
例: null
である name
および description
属性を持つ MyPojo
オブジェクトをデフォルトと想定します。次の例は、MyProperties
から MyPojo
オブジェクトのリストを公開します。
Java
Kotlin
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
private final List<MyPojo> list = new ArrayList<>();
public List<MyPojo> getList() {
return this.list;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my")
class MyProperties {
val list: List<MyPojo> = ArrayList()
}
次の構成を検討してください。
プロパティ
YAML
my.list[0].name=my name
my.list[0].description=my description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
my:
list:
- name: "my name"
description: "my description"
---
spring:
config:
activate:
on-profile: "dev"
my:
list:
- name: "my another name"
dev
プロファイルがアクティブでない場合、MyProperties.list
には、前に定義したように 1 つの MyPojo
エントリが含まれます。ただし、dev
プロファイルが有効になっている場合、list
にはまだ 1 つのエントリしか含まれていません(名前が my another name
で説明が null
)。この構成では、2 番目の MyPojo
インスタンスはリストに追加されず、アイテムはマージされません。
List
が複数のプロファイルで指定されている場合、最高の優先順位を持つプロファイル(およびそのプロファイルのみ)が使用されます。次の例を考えてみましょう。
プロパティ
YAML
my.list[0].name=my name
my.list[0].description=my description
my.list[1].name=another name
my.list[1].description=another description
#---
spring.config.activate.on-profile=dev
my.list[0].name=my another name
my:
list:
- name: "my name"
description: "my description"
- name: "another name"
description: "another description"
---
spring:
config:
activate:
on-profile: "dev"
my:
list:
- name: "my another name"
上記の例で、dev
プロファイルがアクティブである場合、MyProperties.list
には 1 つの MyPojo
エントリ(名前 my another name
および説明 null
)が含まれます。YAML の場合、コンマ区切りリストと YAML リストの両方を使用して、リストの内容を完全にオーバーライドできます。
Map
プロパティの場合、複数のソースから取得したプロパティ値とバインドできます。ただし、複数のソースの同じプロパティの場合、優先度が最も高いプロパティが使用されます。次の例は、MyProperties
から Map<String, MyPojo>
を公開します。
Java
Kotlin
import java.util.LinkedHashMap;
import java.util.Map;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("my")
public class MyProperties {
private final Map<String, MyPojo> map = new LinkedHashMap<>();
public Map<String, MyPojo> getMap() {
return this.map;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
@ConfigurationProperties("my")
class MyProperties {
val map: Map<String, MyPojo> = LinkedHashMap()
}
次の構成を検討してください。
プロパティ
YAML
my.map.key1.name=my name 1
my.map.key1.description=my description 1
#---
spring.config.activate.on-profile=dev
my.map.key1.name=dev name 1
my.map.key2.name=dev name 2
my.map.key2.description=dev description 2
my:
map:
key1:
name: "my name 1"
description: "my description 1"
---
spring:
config:
activate:
on-profile: "dev"
my:
map:
key1:
name: "dev name 1"
key2:
name: "dev name 2"
description: "dev description 2"
dev
プロファイルがアクティブでない場合、MyProperties.map
にはキー key1
(名前 my name 1
および説明 my description 1
)を持つ 1 つのエントリが含まれます。ただし、dev
プロファイルが有効になっている場合、map
には、キー key1
(名前 dev name 1
および説明 my description 1
)および key2
(名前 dev name 2
および説明 dev description 2
)の 2 つのエントリが含まれます。
上記のマージルールは、ファイルだけでなく、すべてのプロパティソースからのプロパティに適用されます。 |
プロパティの変換
Spring Boot は、@ConfigurationProperties
Bean にバインドするときに、外部アプリケーションプロパティを正しい型に強制しようとします。カスタム型の変換が必要な場合は、ConversionService
Bean(conversionService
という名前の Bean を使用)またはカスタムプロパティエディター(CustomEditorConfigurer
Bean を使用)またはカスタム Converters
(@ConfigurationPropertiesBinding
としてアノテーション付けされた Bean 定義を使用)を提供できます。
この Bean はアプリケーションライフサイクルの非常に早い段階でリクエストされるため、ConversionService が使用している依存関係を必ず制限してください。通常、必要な依存関係は作成時に完全に初期化されない場合があります。構成キーの強制に不要なカスタム ConversionService の名前を変更し、@ConfigurationPropertiesBinding で修飾されたカスタムコンバーターのみに依存することができます。 |
時間ベースの期間変換
Spring Boot は、期間を表現するための専用サポートを備えています。java.time.Duration
プロパティを公開する場合、アプリケーションプロパティで次の形式を使用できます。
通常の
long
表現 (@DurationUnit
が指定されていない限り、デフォルトの単位としてミリ秒を使用する)java.time.Duration
が使用する (標準 Javadoc) 標準 ISO-8601 形式値と単位が結合された、より読みやすい形式 (
10s
は 10 秒を意味します)
次の例を考えてみましょう。
Java
Kotlin
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DurationUnit;
@ConfigurationProperties("my")
public class MyProperties {
@DurationUnit(ChronoUnit.SECONDS)
private Duration sessionTimeout = Duration.ofSeconds(30);
private Duration readTimeout = Duration.ofMillis(1000);
// getters / setters...
public Duration getSessionTimeout() {
return this.sessionTimeout;
}
public void setSessionTimeout(Duration sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
public Duration getReadTimeout() {
return this.readTimeout;
}
public void setReadTimeout(Duration readTimeout) {
this.readTimeout = readTimeout;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit
@ConfigurationProperties("my")
class MyProperties {
@DurationUnit(ChronoUnit.SECONDS)
var sessionTimeout = Duration.ofSeconds(30)
var readTimeout = Duration.ofMillis(1000)
}
30 秒のセッションタイムアウトを指定するには、30
、PT30S
、30s
はすべて同等です。500ms の読み取りタイムアウトは、500
、PT0.5S
、500ms
のいずれかの形式で指定できます。
サポートされている任意のユニットを使用することもできます。
ns
ナノ秒us
マイクロ秒ms
ミリ秒s
秒m
分h
時間d
日
デフォルトの単位はミリ秒であり、上記のサンプルに示すように、@DurationUnit
を使用してオーバーライドできます。
コンストラクターバインディングを使用する場合は、次の例に示すように、同じプロパティを公開できます。
Java
Kotlin
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DurationUnit;
@ConfigurationProperties("my")
public class MyProperties {
// fields...
private final Duration sessionTimeout;
private final Duration readTimeout;
public MyProperties(@DurationUnit(ChronoUnit.SECONDS) @DefaultValue("30s") Duration sessionTimeout,
@DefaultValue("1000ms") Duration readTimeout) {
this.sessionTimeout = sessionTimeout;
this.readTimeout = readTimeout;
}
// getters...
public Duration getSessionTimeout() {
return this.sessionTimeout;
}
public Duration getReadTimeout() {
return this.readTimeout;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DurationUnit
import java.time.Duration
import java.time.temporal.ChronoUnit
@ConfigurationProperties("my")
class MyProperties(@param:DurationUnit(ChronoUnit.SECONDS) @param:DefaultValue("30s") val sessionTimeout: Duration,
@param:DefaultValue("1000ms") val readTimeout: Duration)
Long プロパティをアップグレードする場合、ミリ秒でない場合は必ず単位を定義してください(@DurationUnit を使用)。そうすることで、より豊富なフォーマットをサポートしながら、透過的なアップグレードパスが提供されます。 |
期間の変換
時間ベースの期間に加えて、Spring Boot は java.time.Period
型でも機能します。アプリケーションのプロパティでは、次の形式を使用できます。
通常の
int
表現 (@PeriodUnit
が指定されていない限り、デフォルトの単位として日を使用する)java.time.Period
が使用する (標準 Javadoc) 標準 ISO-8601 形式値と単位のペアが結合されたより簡単な形式 (
1y3d
は 1 年 3 日を意味します)
次の単位は、単純な形式でサポートされています。
y
年m
月w
週d
日
java.time.Period 型は実際には週数を格納しません。これは「7 日」を意味するショートカットです。 |
データサイズの変換
Spring Framework には、サイズをバイト単位で表す DataSize
値型があります。DataSize
プロパティを公開する場合、アプリケーションプロパティで次の形式を使用できます。
通常の
long
表現 (@DataSizeUnit
が指定されていない限り、デフォルトの単位としてバイトを使用)値と単位が結合された、より読みやすい形式 (
10MB
は 10 メガバイトを意味します)
次の例を考えてみましょう。
Java
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;
@ConfigurationProperties("my")
public class MyProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize bufferSize = DataSize.ofMegabytes(2);
private DataSize sizeThreshold = DataSize.ofBytes(512);
// getters/setters...
public DataSize getBufferSize() {
return this.bufferSize;
}
public void setBufferSize(DataSize bufferSize) {
this.bufferSize = bufferSize;
}
public DataSize getSizeThreshold() {
return this.sizeThreshold;
}
public void setSizeThreshold(DataSize sizeThreshold) {
this.sizeThreshold = sizeThreshold;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit
@ConfigurationProperties("my")
class MyProperties {
@DataSizeUnit(DataUnit.MEGABYTES)
var bufferSize = DataSize.ofMegabytes(2)
var sizeThreshold = DataSize.ofBytes(512)
}
10 メガバイトのバッファーサイズを指定するには、10
と 10MB
は同等です。256 バイトのサイズしきい値は、256
または 256B
として指定できます。
サポートされている任意のユニットを使用することもできます。
B
バイトKB
キロバイトMB
メガバイトGB
ギガバイトTB
テラバイト
デフォルトの単位はバイトであり、上記のサンプルに示すように @DataSizeUnit
を使用してオーバーライドできます。
コンストラクターバインディングを使用する場合は、次の例に示すように、同じプロパティを公開できます。
Java
Kotlin
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.DefaultValue;
import org.springframework.boot.convert.DataSizeUnit;
import org.springframework.util.unit.DataSize;
import org.springframework.util.unit.DataUnit;
@ConfigurationProperties("my")
public class MyProperties {
// fields...
private final DataSize bufferSize;
private final DataSize sizeThreshold;
public MyProperties(@DataSizeUnit(DataUnit.MEGABYTES) @DefaultValue("2MB") DataSize bufferSize,
@DefaultValue("512B") DataSize sizeThreshold) {
this.bufferSize = bufferSize;
this.sizeThreshold = sizeThreshold;
}
// getters...
public DataSize getBufferSize() {
return this.bufferSize;
}
public DataSize getSizeThreshold() {
return this.sizeThreshold;
}
}
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.bind.DefaultValue
import org.springframework.boot.convert.DataSizeUnit
import org.springframework.util.unit.DataSize
import org.springframework.util.unit.DataUnit
@ConfigurationProperties("my")
class MyProperties(@param:DataSizeUnit(DataUnit.MEGABYTES) @param:DefaultValue("2MB") val bufferSize: DataSize,
@param:DefaultValue("512B") val sizeThreshold: DataSize)
Long プロパティをアップグレードする場合、バイトでない場合は必ず単位を定義してください(@DataSizeUnit を使用)。そうすることで、より豊富なフォーマットをサポートしながら、透過的なアップグレードパスが提供されます。 |
@ConfigurationProperties 検証
Spring Boot は、Spring の @Validated
アノテーションが付けられている場合、@ConfigurationProperties
クラスを検証しようとします。JSR-303 jakarta.validation
制約アノテーションを構成クラスで直接使用できます。これを行うには、次の例に示すように、準拠する JSR-303 実装がクラスパス上にあることを確認してから、フィールドに制約アノテーションを追加します。
Java
Kotlin
import java.net.InetAddress;
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
// getters/setters...
public InetAddress getRemoteAddress() {
return this.remoteAddress;
}
public void setRemoteAddress(InetAddress remoteAddress) {
this.remoteAddress = remoteAddress;
}
}
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress
@ConfigurationProperties("my.service")
@Validated
class MyProperties {
var remoteAddress: @NotNull InetAddress? = null
}
@Validated を使用して構成プロパティを作成する @Bean メソッドにアノテーションを付けることにより、検証をトリガーすることもできます。 |
ネストされたプロパティに対して検証が常にトリガーされるようにするには、プロパティが見つからない場合でも、関連付けられたフィールドに @Valid
のアノテーションを付ける必要があります。次の例は、前述の MyProperties
の例に基づいています。
Java
Kotlin
import java.net.InetAddress;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;
@ConfigurationProperties("my.service")
@Validated
public class MyProperties {
@NotNull
private InetAddress remoteAddress;
@Valid
private final Security security = new Security();
// getters/setters...
public InetAddress getRemoteAddress() {
return this.remoteAddress;
}
public void setRemoteAddress(InetAddress remoteAddress) {
this.remoteAddress = remoteAddress;
}
public Security getSecurity() {
return this.security;
}
public static class Security {
@NotEmpty
private String username;
// getters/setters...
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
}
}
import jakarta.validation.Valid
import jakarta.validation.constraints.NotEmpty
import jakarta.validation.constraints.NotNull
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.validation.annotation.Validated
import java.net.InetAddress
@ConfigurationProperties("my.service")
@Validated
class MyProperties {
var remoteAddress: @NotNull InetAddress? = null
@Valid
val security = Security()
class Security {
@NotEmpty
var username: String? = null
}
}
configurationPropertiesValidator
という Bean 定義を作成して、カスタム Spring Validator
を追加することもできます。@Bean
メソッドは static
として宣言する必要があります。構成プロパティバリデーターは、アプリケーションのライフサイクルの非常に早い段階で作成され、@Bean
メソッドを静的として宣言すると、@Configuration
クラスをインスタンス化せずに Bean を作成できます。そうすることで、早期のインスタンス化によって引き起こされる可能性のある問題を回避できます。
spring-boot-actuator モジュールには、すべての @ConfigurationProperties Bean を公開するエンドポイントが含まれています。Web ブラウザーで /actuator/configprops を指定するか、同等の JMX エンドポイントを使用してください。詳細については、本番対応機能セクションを参照してください。 |
@ConfigurationProperties 対 @Value
@Value
アノテーションはコアコンテナー機能であり、型安全な構成プロパティと同じ機能を提供しません。次の表は、@ConfigurationProperties
および @Value
でサポートされている機能をまとめたものです。
フィーチャー | @ConfigurationProperties | @Value |
---|---|---|
はい | 限定的 ( 以下の注を参照してください) | |
はい | いいえ | |
| いいえ | はい |
例: |
独自のコンポーネントの構成キーのセットを定義する場合は、@ConfigurationProperties
でアノテーションされた POJO にグループ化することをお勧めします。これにより、独自の Bean に注入できる構造化された型安全なオブジェクトが提供されます。
アプリケーションプロパティファイルからの SpEL
式は、これらのファイルを解析して環境にデータを取り込むときに処理されません。ただし、@Value
で SpEL
式を記述することは可能です。アプリケーションプロパティファイルのプロパティの値が SpEL
式の場合、@Value
を介して消費されたときに評価されます。