Spring Boot 參考指南(外部化配置)

24. 外部化配置

Spring Boot容許你外部化你的配置,這樣你就能夠在不一樣的環境中使用相同的應用程序代碼,你可使用properties文件、YAML文件、環境變量和命令行參數來外部化配置,屬性值能夠經過使用@Value註解直接注入到你的bean中,經過Spring的Environment抽象訪問,或者經過@ConfigurationProperties綁定到結構化對象。html

Spring Boot使用一種很是特殊的PropertySource命令,該命令旨在容許對值進行合理的覆蓋,屬性按如下順序考慮:java

  1. Devtools全局設置屬性在你的主目錄(~/.spring-boot-devtools.properties當devtools處於激活狀態時。
  2. 測試中的@TestPropertySource註解
  3. 測試中的@SpringBootTest#properties註解屬性
  4. 命令行參數
  5. 來自SPRING_APPLICATION_JSON(嵌入在環境變量或系統屬性中的內聯JSON)的屬性
  6. ServletConfig初始化參數
  7. ServletContext初始化參數
  8. java:comp/env中的JNDI屬性
  9. Java系統屬性(System.getProperties()
  10. 操做系統環境變量
  11. 一個只有random.*屬性的RandomValuePropertySource
  12. 在你的jar包以外的特殊配置文件的應用程序屬性application-{profile}.propertiesYAML 變體)
  13. 在jar中打包的特殊配置文件的應用程序屬性application-{profile}.propertiesYAML 變體)
  14. 在你的jar包以外的應用程序屬性(application.propertiesYAML 變體)
  15. 打包在jar中的應用程序屬性(application.propertiesYAML 變體)
  16. @PropertySource註解在你的@Configuration類上
  17. 默認屬性(經過設置SpringApplication.setDefaultProperties指定)

爲了提供一個具體的示例,假設你開發了一個使用name屬性的@Component,以下例所示:git

import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean { 

   @Value("${name}")
   private String name;

   // ...
}

在你的應用程序類路徑(例如,在jar包中)你能夠有一個application.properties文件爲name提供一個合理的默認屬性值。在新環境中運行時,能夠在你的jar包以外提供一個application.properties以覆蓋name。對於一次性測試,你可使用特定的命令行開關啓動(例如,java -jar app.jar --name=「Spring」)。github

SPRING_APPLICATION_JSON屬性能夠在帶有環境變量的命令行上提供,例如,你能夠在UN*X shell中使用如下一行:
$ SPRING_APPLICATION_JSON='{"acme":{"name":"test"}}' java -jar myapp.jar
在前面的示例中,在Spring Environment中你最終獲得了 acme.name=test,你也能夠提供JSON做爲 spring.applicatio.json在系統屬性中,以下例所示:
$ java -Dspring.application.json='{"name":"test"}' -jar myapp.jar
你還可使用命令行參數來提供JSON,以下面的示例所示:
$ java -jar myapp.jar --spring.application.json='{"name":"test"}'
你還能夠將JSON做爲JNDI變量提供,以下所示: java:comp/env/spring.application.json

24.1 配置隨機值

RandomValuePropertySource用於注入隨機值(例如,在secrets或測試用例中),它能夠生成integerlonguuidstring,以下面的示例所示:web

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]}

random.int*語法是OPEN value (,max) CLOSEOPEN,CLOSE中是任何字符而且value,max是整數。若是提供了max,那麼value就是最小值,max是最大值(惟一的)。spring

24.2 訪問命令行屬性

在默認狀況下,SpringApplication會轉換任何命令行選項參數(也就是說,參數從--開始,像--server.port=9000)到一個property,並將它們添加到Spring Environment中,如前所述,命令行屬性老是優先於其餘屬性源。shell

若是不但願將命令行屬性添加到Environment中,你可使用SpringApplication.setAddCommandLineProperties(false)禁用它們。json

24.3 應用程序屬性文件

SpringApplication在如下位置從application.properties文件加載屬性並將它們添加到Spring Environment:segmentfault

  1. 當前目錄子目錄的/config
  2. 當前目錄
  3. 類路徑下/config
  4. 類路徑的根目錄

列表按優先順序排序(在列表中較高的位置定義的屬性覆蓋在較低位置定義的屬性)。api

你還可使用 YAML ('.yml')文件做爲 '.properties'的替代。

若是你不喜歡application.properties做爲配置文件名,能夠經過指定spring.config.name環境屬性切換到另外一個文件名,你還可使用spring.config.location環境屬性來引用一個顯式的位置(它是一個逗號分隔的目錄位置或文件路徑列表),下面的示例演示如何指定不一樣的文件名:

$ java -jar myproject.jar --spring.config.name=myproject

下面的示例演示如何指定兩個位置:

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/
override.properties
spring.config.namespring.config.location很早就被用於肯定哪些文件必須被加載,所以它們必須被定義爲環境屬性(一般是一個OS環境變量、一個系統屬性或一個命令行參數)。

若是spring.config.location包含目錄(相對於文件),它們應該以/結束(而且在運行時,附加的名字來自spring.config.name以前被加載,包括特殊配置文件的文件名)。spring.config.location中指定的文件是按原樣使用的,不支持特殊配置文件的變體,而且被任何特殊配置文件的屬性覆蓋。

配置位置按相反順序搜索,默認狀況下,配置的位置是classpath:/classpath:/config/file:./file:./config/。由此產生的搜索順序以下:

  1. file:./config/
  2. file:./
  3. classpath:/config/
  4. classpath:/

當自定義配置位置使用spring.config.location配置時,它們替換默認的位置。例如,若是spring.config.location配置值爲classpath:/custom-config/file:./custom-config/,搜索順序以下:

  1. file:./custom-config/
  2. classpath:custom-config/

或者,當自定義配置位置使用spring.config.additional-location配置時,除了默認位置外,還使用它們,在默認位置以前搜索額外的位置。例如,若是額外位置classpath:/custom-config/file:./custom-config/被配置,搜索順序以下:

  1. file:./custom-config/
  2. classpath:custom-config/
  3. file:./config/
  4. file:./
  5. classpath:/config/
  6. classpath:/

這個搜索排序容許你在一個配置文件中指定默認值,而後在另外一個配置文件中選擇性地覆蓋這些值。你能夠在application.properties爲你的應用程序提供默認值(或你在spring.config.name中選擇的其餘basename)位於默認位置之一。這些默認值能夠在運行時被重寫,並在一個定製的位置中放置一個不一樣的文件。

若是你使用環境變量而不是系統屬性,大多數操做系統都不容許使用週期分隔的鍵名,可是你可使用下劃線(例如, SPRING_CONFIG_NAME而不是 spring.config.name)。
若是應用程序在容器中運行,那麼可使用JNDI屬性(在 java:comp/env)或servlet上下文初始化參數,而不是環境變量或系統屬性。

24.4 特殊配置文件的屬性

除了application.properties文件,特殊配置文件的屬性也能夠經過如下命名約定來定義:application-{profile}.propertiesEnvironment有一組默認配置文件(默認狀況下是[default]),若是沒有設置活動配置文件,則使用默認配置文件。換句話說,若是沒有顯式激活配置文件,則加載application-default.properties中的屬性。

特殊配置文件的屬性從與標準application.properties相同的位置加載,特殊配置文件的文件老是覆蓋非特定的文件,不管特殊配置文件的文件是在打包的jar內部仍是外部。

若是多個特殊配置文件,則使用應用最後一個的策略,例如,由spring.profiles.active屬性添加的特殊配置文件在經過SpringApplication API配置的配置文件以後添加,所以優先級更高。

若是在 spring.config.locaction中指定了任何文件,不考慮這些文件的特定配置文件的變體。若是你還想同時使用特殊配置文件,在 spring.config.location中使用目錄

24.5 屬性中的佔位符

application.properties中的值在使用時經過現有Environment進行過濾,所以你能夠返回到之前定義的值(例如,來自系統屬性)。

app.name=MyApp
app.description=${app.name} is a Spring Boot application
你還可使用此技術來建立現有Spring boot屬性的「Short」變體,詳細信息請參閱第74.4節「使用‘Short’命令行參數」。

24.6 使用YAML代替屬性

YAMLJSON的超集,所以是指定分層配置數據的一種方便的格式,只要類路徑上有SnakeYAML庫,SpringApplication類就會自動支持YAML做爲屬性的替代。

若是你使用「Starters」, SnakeYAML將由 spring-boot-starter自動提供。

24.6.1 加載YAML

Spring框架提供了兩個方便的類,能夠用來加載YAML文檔。YamlPropertiesFactoryBean以屬性裝載YAML,而YamlMapFactoryBeanMap的形式裝載YAML。

例如,參考如下YAML文檔:

environments: 
  dev:
    url: http://dev.example.com
    name: Developer Setup 
  prod:
    url: http://another.example.com 
    name: My Cool App

前面的示例將轉換爲如下屬性:

environments.dev.url=http://dev.example.com 
environments.dev.name=Developer Setup 
environments.prod.url=http://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

經過使用Spring Boot的Binder工具(這是@ConfigurationProperties所作的)來綁定到相似的屬性,你須要在目標bean中有一個java.util.List(或Set)屬性而且還須要提供一個setter或使用變量初始化它。例如,下面的示例綁定到前面顯示的屬性:

@ConfigurationProperties(prefix="my")
public class Config {

  private List<String> servers = new ArrayList<String>();

  public List<String> getServers() { 
    return this.servers;
  } 
}

24.6.2 將YAML公開爲Spring環境中的屬性

YamlPropertySourceLoader類可用於在Spring Environment中將YAML公開爲PropertySource,這樣作可使用帶有佔位符語法的@Value註解來訪問YAML屬性。

24.6.3 多個YAML配置文件

你可使用spring.profiles鍵在單個文件中指定多個特殊配置YAML文檔來指示你文檔什麼時候應用,以下所示:

server:
  address: 192.168.1.100
---
spring:
  profiles: development
server:
  address: 127.0.0.1
---
spring:
  profiles: production
server:
  address: 192.168.1.120

在前面的例子中,若是development配置文件是激活的,server.address屬性是127.0.0.1。相似地,若是production配置文件是激活的,server.address屬性是192.168.1.120。若是不啓用developmentproduction配置文件,則屬性的值爲192.168.1.100

若是在應用程序上下文啓動時沒有顯式激活,默認配置文件被激活。所以,在接下來的YAML中,咱們爲僅在「默認」配置文件中可用的spring.security.user.password設置了一個值:

server: 
  port: 8000
---
spring:
  profiles: default 
  security:
    user:
    password: weak

然而,在下面的示例中,密碼老是被設置,由於它沒有附加到任何配置文件中,並且將在全部其餘配置文件中顯式地設置被重置:

server: 
  port: 8000
spring: 
  security:
    user:
    password: weak

使用spring.profiles元素指定的Spring配置文件能夠選擇性的使用字符否認。若是爲單個文檔指定了否認的和非否認的配置文件,則至少必須匹配一個非否認的配置文件,而且不能匹配任何否認的配置文件。

24.6.4 YAML的缺點

YAML文件不能被@PropertySource註解加載,所以,在須要以這種方式加載值的狀況下,須要使用屬性文件。

24.7 類型安全的配置屬性文件

使用@Value(「${property}」)註解注入配置屬性有時會很麻煩,尤爲是當你處理多個屬性或你的數據本質上是層次化的時候,Spring Boot提供了另外一種處理屬性的方法,該方法容許強類型bean管理和驗證應用程序的配置。

package com.example;

import java.net.InetAddress; 
import java.util.ArrayList; 
import java.util.Collections; 

import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties; 

@ConfigurationProperties("acme")
public class AcmeProperties {
    
    private boolean enabled;
    private InetAddress remoteAddress;
    
    private final Security security = new Security();

    public boolean isEnabled() { ... }
    
    public void setEnabled(boolean enabled) { ... }

    public InetAddress getRemoteAddress() { ... }

    public void setRemoteAddress(InetAddress remoteAddress) { ... } 

    public Security getSecurity() { ... }

    public static class Security {

        private String username;
        private String password;

        private List<String> roles = new ArrayList<>(Collections.singleton("USER")); 

        public String getUsername() { ... }
        
        public void setUsername(String username) { ... }
        
        public String getPassword() { ... }
        
        public void setPassword(String password) { ... }
        
        public List<String> getRoles() { ... }
        
        public void setRoles(List<String> roles) { ... }
    } 
}

前一個POJO定義瞭如下屬性:

  • acme.enabled,默認值爲false
  • acme.remote-address,能夠從String強轉的類型
  • acme.security.username,使用嵌套的「 security」對象,該對象的名稱由屬性的名稱決定,特別是,返回類型根本不使用,而且多是SecurityProperties
  • acme.security.password
  • acme.security.roles,使用一個String集合

getter和setter一般是強制性的,由於綁定是經過標準的Java bean屬性描述符,就像在Spring MVC中同樣,在如下狀況下能夠省略setter:

  • Map,只要初始化了它們,就須要一個getter,但不必定須要setter,由於綁定器能夠對它們進行轉變。
  • 能夠經過索引(一般是YAML)或使用單個逗號分隔值(屬性)來訪問集合和數組,在後一種狀況下,setter是必需的。咱們建議始終爲此類類型添加一個setter,若是初始化一個集合,請確保它不是不可變的(如前面的示例所示)。
  • 若是初始化嵌套POJO屬性(如前面示例中的Security字段),則不須要setter,若是你但願綁定器使用它的默認構造函數來動態建立實例,那麼你須要一個setter。

有些人使用Lombok項目自動添加getter和setter,確保Lombok沒有爲此類類型生成任何特定的構造函數,由於容器會自動使用它來實例化對象。

最後,只考慮標準的Java Bean屬性,不支持對靜態屬性的綁定。


還能夠查看 @Value@ConfigurationProperties之間的差別。

你還須要列出要在@EnableConfigurationProperties註解中註冊的屬性類,以下例所示:

@Configuration 
@EnableConfigurationProperties(AcmeProperties.class) 
public class MyConfiguration {
}
當以 @ConfigurationProperties這種方式註冊bean時,bean有一個常規名稱: <prefix>-<fqn>,其中 <prefix>是在 @ConfigurationProperties註解中指定的環境key前綴, <fqn>是bean的徹底限定名,若是註解不提供任何前綴,則只使用bean的徹底限定名。

上面示例中的bean名稱是acme-com.example.AcmeProperties

即便前面的配置爲AcmeProperties建立了一個常規bean,咱們建議@ConfigurationProperties只處理環境,特別是從上下文中不注入其餘bean。話雖如此,@EnableConfigurationProperties註解也自動應用於你的項目,使任何已添加@ConfigurationProperties註解的bean均可以從Environment中配置。你能夠經過確保AcmeProperties已是一個bean來簡化MyConfiguration,以下面的示例所示:

@Component 
@ConfigurationProperties(prefix="acme") 
public class AcmeProperties {
 // ... see the preceding example
}

這種配置風格與SpringApplication外部YAML配置配合得特別好,以下例所示:

# application.yml

acme:
  remote-address: 192.168.1.1
  security: 
    username: admin 
    roles:
      - USER 
      - ADMIN
# additional configuration as required

要使用@ConfigurationProperties bean,能夠像其餘bean同樣對它們進行注入,以下例所示:

@Service
public class MyService {

  private final AcmeProperties properties;

  @Autowired
  public MyService(AcmeProperties properties) { 
    this.properties = properties;
  }

  //...
 
  @PostConstruct
  public void openConnection() {
    Server server = new Server(this.properties.getRemoteAddress()); 
    // ...
  } 
}
使用 @ConfigurationProperties還能夠生成能夠被IDE使用的元數據文件,爲你本身的鍵提供自動完成。詳細信息請參閱 附錄B,配置元數據附錄

24.7.1 第三方配置

除了使用@ConfigurationProperties來註解類以外,還能夠在公開的@Bean方法中使用它,當你但願將屬性綁定到控件以外的第三方組件時,這樣作特別有用。

要從Environment屬性配置bean,請向其bean註冊中添加@ConfigurationProperties,以下例所示:

@ConfigurationProperties(prefix = "another") 
@Bean
public AnotherComponent anotherComponent() {
  ... 
}

another前綴定義的任何屬性都被映射到與前面的AcmeProperties示例相似的另外一個組件bean。

24.7.2 寬鬆綁定

Spring Boot使用一些寬鬆的規則將Environment屬性綁定到@ConfigurationProperties bean,所以不須要在Environment屬性名和bean屬性名之間進行精確匹配,這頗有用的常見示例包括:分體環境屬性(例如,context-path綁定到contextPath)和大寫的環境屬性(例如,PORT綁定到port)。

例如,參考下面的@ConfigurationProperties類:

@ConfigurationProperties(prefix="acme.my-project.person")
public class OwnerProperties {

  private String firstName;

  public String getFirstName() { 
    return this.firstName;
  }

  public void setFirstName(String firstName) { 
    this.firstName = firstName;
  }  
}

在前面的示例中,可使用如下屬性名稱:

屬性 提示
acme.my-project.person.first-name 鏈接符形式,建議在.properties.yml文件中使用
acme.myProject.person.firstName 標準的駝峯式大小寫語法
acme.my_project.person.first_name 下劃線表示法,這是在.properties.yml文件中使用的另外一種格式
ACME_MYPROJECT_PERSON_FIRSTNAME 在使用系統環境變量時推薦使用大寫格式
註解的 prefix值必須使用鏈接符形式(小寫而且使用 -分隔,如 acme.my-project.person)。

表24.2,放寬了每一個屬性源的綁定規則

屬性源 樣例 列表
屬性文件 駝峯式大小寫,鏈接符大小寫,或下劃線符號 使用[]或逗號分隔值的標準列表語法
YAML文件 駝峯式大小寫,鏈接符大小寫,或下劃線符號 標準的YAML列表語法或逗號分隔的值
環境變量 如下劃線做爲分隔符的大寫格式,不該該在屬性名中使用_ 由下劃線包圍的數值,例如MY_ACME_1_OTHER = my.acme[1].other
系統屬性 駝峯式大小寫,鏈接符大小寫,或下劃線符號 使用[]或逗號分隔值的標準列表語法
咱們建議,在可能的狀況下,屬性以小寫的鏈接符格式存儲,例如 my.property-name=acme

在綁定到Map屬性時,若是key不包含小寫字母數字字符或-,則須要使用括號符號,以便保留原始值。若是鍵沒有被[]包圍,任何非字母數字或-的字符都會被刪除,例如,考慮將如下屬性綁定到Map

acme:
  map:
    "[/key1]": value1
    "[/key2]": value2
    /key3: value3

上面的屬性將綁定到以/key1/key2key3做爲Map中的鍵的Map

24.7.3 合併複雜類型

當在多個地方配置列表時,經過替換整個列表來重寫。

例如,假設一個MyPojo對象的namedescription屬性默認爲null,下面的示例公開了來自AcmePropertiesMyPojo對象列表:

@ConfigurationProperties("acme")
public class AcmeProperties {

    private final List<MyPojo> list = new ArrayList<>();

    public List<MyPojo> getList() {
        return this.list;
    }

}

參考以下配置:

acme:
  list:
    - name: my name
      description: my description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

若是dev配置文件不是激活的,AcmeProperties.list包含一個MyPojo條目,正如前面定義的。若是啓用了dev配置文件,然而,該列表仍然只包含一個條目,(以my another name的名稱和null的描述),此配置不向列表添加第二個MyPojo實例,也不合並條目。

當一個List在多個配置文件中指定時,使用具備最高優先級的(且僅使用該優先級),參考下面的例子:

acme:
  list:
    - name: my name
      description: my description
    - name: another name
      description: another description
---
spring:
  profiles: dev
acme:
  list:
    - name: my another name

在前面的例子,若是dev配置文件是激活的,AcmeProperties.list包含一個MyPojo條目(以my another name做爲name和null的description),對於YAML,可使用逗號分隔的列表和YAML列表徹底覆蓋列表的內容。

對於Map屬性,你可使用來自多個源的屬性值進行綁定,可是,對於多個源中的相同屬性,使用優先級最高的屬性。下面的示例公開了AcmePropertiesMap<String, MyPojo>:

@ConfigurationProperties("acme")
public class AcmeProperties {

    private final Map<String, MyPojo> map = new HashMap<>();

    public Map<String, MyPojo> getMap() {
        return this.map;
    }

}

參考以下配置:

acme:
  map:
    key1:
      name: my name 1
      description: my description 1
---
spring:
  profiles: dev
acme:
  map:
    key1:
      name: dev name 1
    key2:
      name: dev name 2
      description: dev description 2

若是dev配置文件不是激活的,AcmeProperties.map包含一個鍵key1的條目(一個my name 1的name和一個my description 1的description)。若是啓用了dev配置文件,然而,map包含鍵key1(name爲dev name 1,description爲my description 1)和key2(name爲dev name 2,description爲dev description 2)的兩個條目。

前面的合併規則適用於來自全部屬性源的屬性,而不只僅是YAML文件。

24.7.4 屬性轉換

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.util.Duration的標準的ISO-8601格式
  • 一個更可讀的格式,其中的值和單位是耦合的(例如,10s意味着10秒)

參考下面的例子:

@ConfigurationProperties("app.system")
public class AppSystemProperties {

    @DurationUnit(ChronoUnit.SECONDS)
    private Duration sessionTimeout = Duration.ofSeconds(30);

    private Duration readTimeout = Duration.ofMillis(1000);

    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;
    }

}

指定30秒的會話超時,30PT30S30s都是等價的,能夠在如下任何形式中指定500ms的讀超時:500PT0.5S500ms

你還可使用任何受支持的單元,這些都是:

  • 納秒使用ns
  • 毫秒使用ms
  • 秒使用s
  • 分鐘使用m
  • 小時使用h
  • 天使用d

默認的單位是毫秒,可使用@DurationUnit覆蓋,如上面的示例所示。

若是你正在升級之前的版本,只是使用 Long來表示持續時間,若是不是在切換到 Duration時的毫秒數,確保定義單元(使用 @DurationUnit)。這樣作能夠提供透明的升級路徑,同時支持更豐富的格式。

24.7.5 @ConfigurationProperties Validation

每當使用Spring的@validate註解@ConfigurationProperties類時,Spring Boot都會嘗試驗證這些類。你能夠直接在配置類上使用JSR-303 javax.validation約束註解。爲此,請確保在你的類路徑上有一個兼容的JSR-303實現,而後向你的字段添加約束註解,以下面的示例所示:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

    @NotNull
    private InetAddress remoteAddress;

    // ... getters and setters

}
你還能夠經過註解 @Bean方法來觸發驗證,該方法使用 @Validated建立配置屬性。

儘管嵌套屬性在綁定時也會被驗證,將相關字段註解爲@Valid是很好的實踐,這確保即便沒有找到嵌套屬性,也會觸發驗證。如下示例基於前面的AcmeProperties示例:

@ConfigurationProperties(prefix="acme")
@Validated
public class AcmeProperties {

    @NotNull
    private InetAddress remoteAddress;

    @Valid
    private final Security security = new Security();

    // ... getters and setters

    public static class Security {

        @NotEmpty
        public String username;

        // ... getters and setters

    }

}

你還能夠經過建立一個名爲configurationPropertiesValidator的bean定義來添加一個定製的Spring Validator@Bean方法應該聲明爲static,配置屬性驗證器是在應用程序生命週期的早期建立的,而且將@Bean方法聲明爲靜態,這樣就能夠建立bean,而沒必要實例化@Configuration類。這樣作能夠避免早期實例化可能致使的任何問題。這裏有一個屬性驗證示例,展現瞭如何設置。

spring-boot-actuator模塊包含公開全部 @ConfigurationProperties bean的端點,將web瀏覽器指向 /actuator/configprops或使用等效的JMX端點。有關詳細信息,請參閱「 生產就緒特性」一節。

24.7.6 @ConfigurationProperties和@Value

@Value註解是一個核心容器特性,它不提供與類型安全配置屬性相同的特性,下表總結了@ConfigurationProperties@Value支持的特性:

特性 @ConfigurationProperties @Value
寬鬆綁定 YES NO
元數據支持 YES NO
SpEL評估 NO YES

若是你爲本身的組件定義了一組配置鍵,咱們建議你將它們分組到帶有@ConfigurationProperties註解的POJO中。你還應該注意,因爲@Value不支持寬鬆綁定,所以若是你須要經過使用環境變量來提供值,那麼它不是一個很好的選擇。

最後,當你能夠在@Value中編寫SpEL表達式,這些表達式不會從應用程序屬性文件中處理。


上一篇:SpringApplication

下一篇:配置文件

相關文章
相關標籤/搜索