アノテーションプロセッサーを使用して独自のメタデータを生成する
spring-boot-configuration-processor
jar を使用すると、@ConfigurationProperties
(Javadoc) でアノテーションが付けられた項目から独自の構成メタデータファイルを簡単に生成できます。jar には、プロジェクトのコンパイル時に呼び出される Java アノテーションプロセッサーが含まれています。
アノテーションプロセッサーの構成
Maven を使用してビルドする場合は、コンパイラープラグイン (3.12.0 以降) を構成して、アノテーションプロセッサーパスに spring-boot-configuration-processor
を追加します。
<project>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
</project>
Gradle では、次の例に示すように、annotationProcessor
構成で依存関係を宣言する必要があります。
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
additional-spring-configuration-metadata.json
ファイルを使用している場合、compileJava
タスクは、次の例に示すように、processResources
タスクに依存するように構成する必要があります。
tasks.named('compileJava') {
inputs.files(tasks.named('processResources'))
}
この依存関係により、コンパイル中にアノテーションプロセッサーが実行されるときに追加のメタデータが使用可能になります。
プロジェクトで AspectJ を使用している場合は、アノテーションプロセッサーが 1 回だけ実行されることを確認する必要があります。これを行うにはいくつかの方法があります。Maven を使用すると、
|
プロジェクトで Lombok を使用している場合は、そのアノテーションプロセッサーが |
自動メタデータ生成
プロセッサーは、@ConfigurationProperties
(Javadoc) でアノテーションが付けられたクラスとメソッドの両方を取得します。
@ConfigurationProperties (Javadoc) でメタアノテーションが付けられたカスタムアノテーションはサポートされていません。 |
クラスにパラメーター化されたコンストラクターが 1 つある場合、コンストラクターに @Autowired
(Javadoc) のアノテーションが付けられていない限り、コンストラクターパラメーターごとに 1 つのプロパティが作成されます。クラスに @ConstructorBinding
(Javadoc) のアノテーションが明示的に付けられたコンストラクターがある場合、そのコンストラクターのコンストラクターパラメーターごとに 1 つのプロパティが作成されます。それ以外の場合、プロパティは、標準の getter および setter の存在によって検出され、コレクション型およびマップ型に対して特別な処理が行われます (getter のみが存在する場合でも検出されます)。アノテーションプロセッサーは、@Data
(英語) 、@Value
(英語) 、@Getter
(英語) 、@Setter
(英語) lombok アノテーションの使用もサポートします。
次の例を考えてみましょう。
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.server")
public class MyServerProperties {
/**
* Name of the server.
*/
private String name;
/**
* IP address to listen to.
*/
private String ip = "127.0.0.1";
/**
* Port to listener to.
*/
private int port = 9797;
// getters/setters ...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getIp() {
return this.ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
// fold:off
}
これにより、my.server.name
にはデフォルトがなく、my.server.ip
および my.server.port
のデフォルトはそれぞれ "127.0.0.1"
および 9797
の 3 つのプロパティが公開されます。フィールドの Javadoc は、description
属性を設定するために使用されます。たとえば、my.server.ip
の記述は「リッスンする IP アドレス」です。
@ConfigurationProperties (Javadoc) フィールドの Javadoc ではプレーンテキストのみを使用する必要があります。プレーンテキストは JSON に追加される前に処理されないためです。 |
レコードクラスで @ConfigurationProperties
(Javadoc) を使用する場合、レコードコンポーネントの説明はクラスレベルの Javadoc タグ @param
を介して提供される必要があります (レコードクラスには、通常のフィールドレベルの Javadoc を配置するための明示的なインスタンスフィールドはありません)。
アノテーションプロセッサーは、ソースモデルからデフォルト値を抽出するために、いくつかのヒューリスティックを適用します。デフォルト値は静的に提供する必要があります。特に、別のクラスで定義された定数を参照しないでください。また、アノテーションプロセッサーは、Collections
のデフォルト値を自動検出することはできません。
デフォルト値を検出できなかった場合は、手動のメタデータを提供する必要があります。次の例について考えてみます。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.messaging")
public class MyMessagingProperties {
private List<String> addresses = new ArrayList<>(Arrays.asList("a", "b"));
private ContainerType containerType = ContainerType.SIMPLE;
// getters/setters ...
public List<String> getAddresses() {
return this.addresses;
}
public void setAddresses(List<String> addresses) {
this.addresses = addresses;
}
public ContainerType getContainerType() {
return this.containerType;
}
public void setContainerType(ContainerType containerType) {
this.containerType = containerType;
}
public enum ContainerType {
SIMPLE, DIRECT
}
}
上記のクラスのプロパティのデフォルト値をドキュメント化するには、モジュールの手動メタデータに次のコンテンツを追加できます。
{"properties": [
{
"name": "my.messaging.addresses",
"defaultValue": ["a", "b"]
},
{
"name": "my.messaging.container-type",
"defaultValue": "simple"
}
]}
既存のプロパティの追加のメタデータをドキュメント化するには、プロパティの name のみが必要です。 |
ネストされたプロパティ
アノテーションプロセッサーは自動的に内部クラスをネストされたプロパティと見なします。名前空間のルートで ip
と port
をドキュメント化する代わりに、サブ名前空間を作成できます。更新された例を考えてみましょう:
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "my.server")
public class MyServerProperties {
private String name;
private Host host;
// getters/setters ...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Host getHost() {
return this.host;
}
public void setHost(Host host) {
this.host = host;
}
public static class Host {
private String ip;
private int port;
// getters/setters ...
public String getIp() {
return this.ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
// @fold:off // getters/setters ...
}
}
上記の例では、my.server.name
、my.server.host.ip
、my.server.host.port
プロパティのメタデータ情報が生成されます。フィールドまたは getter メソッドで @NestedConfigurationProperty
(Javadoc) アノテーションを使用して、通常の (内部ではない) クラスをネストされているかのように扱う必要があることを示すことができます。
これらの型は自動的に識別され、それぞれに対して単一のメタデータプロパティが生成されるため、これはコレクションやマップには影響しません。 |
メタデータを追加する
Spring Boot の構成ファイルの処理は非常に柔軟で、@ConfigurationProperties
(Javadoc) Bean にバインドされていないプロパティが存在することがよくあります。また、既存のキーの一部の属性を調整する必要がある場合もあります。このようなケースをサポートし、カスタムの「ヒント」を提供できるようにするために、アノテーションプロセッサーは META-INF/additional-spring-configuration-metadata.json
の項目をメインのメタデータファイルに自動的にマージします。
自動的に検出されたプロパティを参照する場合、説明、デフォルト値、非推奨情報は、指定されていれば上書きされます。手動プロパティ宣言が現在のモジュールで識別されない場合、新しいプロパティとして追加されます。
additional-spring-configuration-metadata.json
ファイルの形式は、通常の spring-configuration-metadata.json
とまったく同じです。追加のプロパティファイルはオプションです。追加のプロパティがない場合は、ファイルを追加しないでください。