使用註解處理器產生您自己的元數據
您可以使用 spring-boot-configuration-processor
jar,從標註 @ConfigurationProperties
的項目輕鬆產生您自己的組態元數據檔案。此 jar 包含一個 Java 註解處理器,它會在您的專案編譯時被調用。
組態註解處理器
若要使用此處理器,請包含 spring-boot-configuration-processor
的依賴。
對於 Maven,此依賴應宣告為可選,如下列範例所示
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
對於 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,則需要確保註解處理器僅執行一次。有多種方法可以執行此操作。使用 Maven,您可以明確地組態
|
如果您在專案中使用 Lombok,則需要確保其註解處理器在 |
自動元數據產生
處理器會挑選以 @ConfigurationProperties
註解的類別和方法。
不支援使用 @ConfigurationProperties 元註解的自訂註解。 |
如果類別具有單一參數化建構子,則會為每個建構子參數建立一個屬性,除非該建構子以 @Autowired
註解。如果類別具有以 @ConstructorBinding
明確註解的建構子,則會為該建構子的每個建構子參數建立一個屬性。否則,會透過標準 getter 和 setter 的存在來探索屬性,並針對集合和 Map 類型進行特殊處理(即使僅存在 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
。欄位上的 Javadoc 用於填入 description
屬性。例如,my.server.ip
的描述為「IP 位址以進行監聽」。
您應該僅將純文字與 @ConfigurationProperties 欄位 Javadoc 一起使用,因為它們在新增至 JSON 之前不會被處理。 |
如果您將 @ConfigurationProperties
與 record 類別一起使用,則應透過類別層級 Javadoc 標籤 @param
提供 record 組件的描述(在 record 類別中沒有明確的實例欄位來放置常規欄位層級 Javadoc)。
註解處理器會應用許多啟發式方法,從來源模型中提取預設值。預設值必須以靜態方式提供。特別是,不要參考在另一個類別中定義的常數。此外,註解處理器無法自動偵測 Enum
和 Collection
的預設值。
對於無法偵測到預設值的情況,應提供手動元數據。考慮下列範例
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
屬性的元數據資訊。您可以在欄位上使用 @NestedConfigurationProperty
註解,以指示應將常規(非內部)類別視為巢狀類別。
這對集合和 Map 沒有影響,因為這些類型會自動識別,並且會為每個類型產生單一元數據屬性。 |
新增額外元數據
Spring Boot 的組態檔案處理非常彈性,而且通常情況下,可能存在未繫結至 @ConfigurationProperties
bean 的屬性。您可能也需要調整現有金鑰的某些屬性。為了支援這些情況並讓您提供自訂「提示」,註解處理器會自動將來自 META-INF/additional-spring-configuration-metadata.json
的項目合併到主要元數據檔案中。
如果您參考已自動偵測到的屬性,則描述、預設值和棄用資訊會被覆寫(如果已指定)。如果手動屬性宣告在目前的模組中未識別,則會將其新增為新屬性。
additional-spring-configuration-metadata.json
檔案的格式與常規 spring-configuration-metadata.json
完全相同。額外的屬性檔案是可選的。如果您沒有任何額外屬性,請勿新增檔案。