本文翻譯自: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.7 類型安全配置Properties
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>