[翻譯]Spring Boot 特征參考2——外部配置:下

本文翻譯自:http://docs.spring.io/spring-boot/docs/2.0.0.M2/reference/htmlsingle/

詳細(xì)介紹Spring boot的關(guān)鍵特征,針對(duì)有一定springboot基礎(chǔ)的同學(xué)。

目錄

  • 1 外部配置
    • 1.7 類型安全配置Properties
      • 1.7.1 第三方配置
      • 1.7.2 輕松綁定
      • 1.7.3 屬性轉(zhuǎn)換
      • 1.7.4 @ConfigurationProperties驗(yàn)證
      • 1.7.5 @ConfigurationProperties vs. @Value

1. 外部配置

1.7 類型安全配置Properties

使用@Value(“$ {property}”)注釋來(lái)注入配置屬性有時(shí)可能很麻煩,特別是如果您正在使用多個(gè)屬性或數(shù)據(jù)是層次結(jié)構(gòu)的屬性。 Spring Boot提供了一種處理屬性的替代方法,它允許強(qiáng)類型bean來(lái)管理和驗(yàn)證應(yīng)用程序的配置。

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("foo")
public class FooProperties {

    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定義了以下屬性:

  • foo.enabled,默認(rèn)為false
  • foo.remote-address,可以強(qiáng)轉(zhuǎn)為String
  • foo.security.username強(qiáng)制的類型,其中嵌套的“安全性”的名稱由屬性名稱決定。特別是返回類型并沒(méi)有被使用,并且可以是SecurityProperties
  • foo.security.password
  • foo.security.roles,其中包含String

注意:

Getters和setter通常是強(qiáng)制性的,因?yàn)榻壎ㄊ峭ㄟ^(guò)標(biāo)準(zhǔn)的Java Beans屬性描述符,就像在Spring MVC中一樣。在某些情況下可能會(huì)忽略一個(gè)設(shè)置器:

  • 只要初始化它們就需要一個(gè)getter,但不一定是一個(gè)setter,因?yàn)樗鼈兛梢员籦inder綁定。
  • 集合和數(shù)組可以通過(guò)索引(通常使用YAML)或使用單個(gè)逗號(hào)分隔值(屬性)來(lái)訪問(wèn)。在后一種情況下,設(shè)置者是強(qiáng)制性的。我們建議您始終為此類型添加一個(gè)設(shè)置器。如果初始化集合,請(qǐng)確保它不是不可變的(如上例)
  • 如果已初始化嵌套POJO屬性(如上例中的Security字段),則不需要setter。如果您希望binder使用其默認(rèn)構(gòu)造函數(shù)即時(shí)創(chuàng)建實(shí)例,則需要一個(gè)setter。

有些人使用Project Lombok自動(dòng)添加getter和setter。確保Lombok不會(huì)為此類型生成任何特定的構(gòu)造函數(shù)因?yàn)樗鼘⒈蝗萜髯詣?dòng)使用來(lái)實(shí)例化對(duì)象。

您還需要列出要在@EnableConfigurationProperties注釋中注冊(cè)的屬性類:

@Configuration
@EnableConfigurationProperties(FooProperties.class)
public class MyConfiguration {
}

注意:

當(dāng)@ConfigurationProperties bean以這種方式注冊(cè)時(shí),該bean將具有常規(guī)名稱:<prefix>-<fqn>,在@ConfigurationProperties注釋中指定的環(huán)境密鑰前綴<prefix>和bean的完全限定名稱<fqn>。如果注釋不提供任何前綴,則僅使用該bean的完全限定名稱。
上面示例中的bean名稱將是foo-com.example.FooProperties。

即使上述配置將為FooProperties創(chuàng)建一個(gè)常規(guī)bean,我們建議@ConfigurationProperties僅通過(guò)Environment處理,特別是不從上下文中注入其他bean。話雖如此,@EnableConfigurationProperties注釋也會(huì)自動(dòng)應(yīng)用于您的項(xiàng)目,以便使用@ConfigurationProperties注釋的所有現(xiàn)有bean都將從Environment配置。您可以通過(guò)確保FooProperties已經(jīng)是一個(gè)bean來(lái)快速上面的MyConfiguration

@Component
@ConfigurationProperties(prefix="foo")
public class FooProperties {

    // ... see above

}

這種配置方式與SpringApplication外部YAML配置相當(dāng):

# application.yml

foo:
    remote-address: 192.168.1.1
    security:
        username: foo
        roles:
          - USER
          - ADMIN

# additional configuration as required

要使用@ConfigurationProperties bean,您可以像其他任何bean一樣注入它們。

@Service
public class MyService {

    private final FooProperties properties;

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

     //...

    @PostConstruct
    public void openConnection() {
        Server server = new Server(this.properties.getRemoteAddress());
        // ...
    }

}

使用@ConfigurationProperties還可以生成IDE可以為自己的密鑰提供自動(dòng)完成的元數(shù)據(jù)文件。

1.7.1 第三方配置

除了使用@ConfigurationProperties來(lái)注釋類,還可以在public @Bean方法中使用它。當(dāng)您希望將屬性綁定到不受控制的第三方組件時(shí),這可能特別有用。

要從Environment屬性配置一個(gè)bean,請(qǐng)將@ConfigurationProperties添加到其Bean注冊(cè)中:

@ConfigurationProperties(prefix = "bar")
@Bean
public BarComponent barComponent() {
    ...
}

使用bar前綴定義的任何屬性將以與上述FooProperties示例類似的方式映射到該BarComponent bean上

1.7.2 輕松綁定

Spring Boot使用一些輕松的規(guī)則將Environment屬性綁定到@ConfigurationProperties bean,因此不需要在Environment屬性名稱和bean屬性名稱之間進(jìn)行完全匹配。常用的例子是有用的,例如虛線分隔(例如上下文路徑綁定到contextPath)和大寫(xiě)(例如PORT綁定到端口)環(huán)境屬性。例如,給定以下@ConfigurationProperties類:

@ConfigurationProperties(prefix="person")
public class OwnerProperties {

    private String firstName;

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

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

}

可以使用以下屬性名稱:

屬性 注意
person.firstName 標(biāo)準(zhǔn)駝峰語(yǔ)法。
person.first-name 虛擬符號(hào),推薦用于.properties和.yml文件。
person.first_name 下劃線符號(hào),用于.properties和.yml文件的替代格式。
PERSON_FIRST_NAME 大寫(xiě)格式。推薦使用系統(tǒng)環(huán)境變量時(shí)。
1.7.3 屬性轉(zhuǎn)換

當(dāng)Spring綁定到@ConfigurationProperties bean時(shí),Spring將嘗試將外部應(yīng)用程序?qū)傩詮?qiáng)制為正確的類型。如果需要自定義類型轉(zhuǎn)換,您可以提供ConversionService bean(使用bean id conversionService)或自定義屬性編輯器(通過(guò)CustomEditorConfigurer bean)或自定義轉(zhuǎn)換器(使用注釋為@ConfigurationPropertiesBinding的bean定義)。

注意:

由于在應(yīng)用程序生命周期中早期請(qǐng)求了該bean,因此請(qǐng)確保限制ConversionService正在使用的依賴關(guān)系。通常,您需要的任何依賴項(xiàng)可能在創(chuàng)建時(shí)可能未完全初始化。如果配置密鑰強(qiáng)制不需要,并且僅依賴使用@ConfigurationPropertiesBinding限定的自定義轉(zhuǎn)換器,則可能需要重命名自定義ConversionService

1.7.4 @ConfigurationProperties驗(yàn)證

Spring引導(dǎo)將嘗試使用Spring的@Validated注釋來(lái)注釋@ConfigurationProperties類。您可以直接在配置類上使用JSR-303 javax.validation約束注釋。只需確保您的類路徑中符合JSR-303的實(shí)現(xiàn),然后在您的字段中添加約束注釋:

@ConfigurationProperties(prefix="foo")
@Validated
public class FooProperties {

    @NotNull
    private InetAddress remoteAddress;

    // ... getters and setters

}

為了驗(yàn)證嵌套屬性的值,您必須將關(guān)聯(lián)字段注釋為@Valid以觸發(fā)其驗(yàn)證。例如,基于上述FooProperties示例:

@ConfigurationProperties(prefix="connection")
@Validated
public class FooProperties {

    @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

    }

}

您還可以通過(guò)創(chuàng)建名為configurationPropertiesValidator的bean定義來(lái)添加自定義的Spring Validator@Bean方法應(yīng)該聲明為靜態(tài)的。配置屬性驗(yàn)證器是在應(yīng)用程序的生命周期早期創(chuàng)建的,并聲明@Bean方法,因?yàn)?em>static允許創(chuàng)建bean,而無(wú)需實(shí)例化@Configuration類。這避免了早期實(shí)例化可能引起的任何問(wèn)題。有一個(gè)屬性驗(yàn)證樣本,所以你可以看到如何設(shè)置。

注意:

spring-boot-actuator模塊包括一個(gè)暴露所有@ConfigurationProperties bean的端點(diǎn)。只需將您的Web瀏覽器指向/configprops或使用等效的JMX終結(jié)點(diǎn)。

1.7.5 @ConfigurationProperties vs. @Value

@Value是核心容器功能,它不提供與類型安全配置屬性相同的功能。下表總結(jié)了@ConfigurationProperties@Value支持的功能:

Feature @ConfigurationProperties @Value
Relaxed binding Yes No
Meta-data support Yes No
SpEL evaluation No Yes

如果您為自己的組件定義了一組配置密鑰,我們建議您可以將它們分組到使用@ConfigurationProperties注釋的POJO中。還請(qǐng)注意,由于@Value不支持輕松綁定,如果您需要使用環(huán)境變量提供該值,那么它不是一個(gè)很好的候選人。最后,當(dāng)您可以在@Value中編寫(xiě)一個(gè)SpEL表達(dá)式時(shí),這些表達(dá)式不會(huì)從應(yīng)用程序?qū)傩晕募幚怼?/p>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容