本文翻譯自:http://docs.spring.io/spring-boot/docs/2.0.0.M2/reference/htmlsingle/
詳細(xì)介紹Spring boot的關(guān)鍵特征,針對有一定springboot基礎(chǔ)的同學(xué)指巡。
目錄
- 1 外部配置
- 1.7 類型安全配置Properties
- 1.7.1 第三方配置
- 1.7.2 輕松綁定
- 1.7.3 屬性轉(zhuǎn)換
- 1.7.4 @ConfigurationProperties驗證
- 1.7.5 @ConfigurationProperties vs. @Value
- 1.7 類型安全配置Properties
1. 外部配置
1.7 類型安全配置Properties
使用@Value(“$ {property}”)注釋來注入配置屬性有時可能很麻煩犁钟,特別是如果您正在使用多個屬性或數(shù)據(jù)是層次結(jié)構(gòu)的屬性。 Spring Boot提供了一種處理屬性的替代方法稚字,它允許強(qiáng)類型bean來管理和驗證應(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)制的類型瘫想,其中嵌套的“安全性”的名稱由屬性名稱決定。特別是返回類型并沒有被使用昌讲,并且可以是SecurityProperties
- foo.security.password
- foo.security.roles国夜,其中包含String
注意:
Getters和setter通常是強(qiáng)制性的,因為綁定是通過標(biāo)準(zhǔn)的Java Beans屬性描述符短绸,就像在Spring MVC中一樣车吹。在某些情況下可能會忽略一個設(shè)置器:
- 只要初始化它們就需要一個getter筹裕,但不一定是一個setter,因為它們可以被binder綁定窄驹。
- 集合和數(shù)組可以通過索引(通常使用YAML)或使用單個逗號分隔值(屬性)來訪問饶碘。在后一種情況下,設(shè)置者是強(qiáng)制性的馒吴。我們建議您始終為此類型添加一個設(shè)置器扎运。如果初始化集合,請確保它不是不可變的(如上例)
- 如果已初始化嵌套POJO屬性(如上例中的Security字段)饮戳,則不需要setter豪治。如果您希望binder使用其默認(rèn)構(gòu)造函數(shù)即時創(chuàng)建實例,則需要一個setter扯罐。
有些人使用Project Lombok自動添加getter和setter负拟。確保Lombok不會為此類型生成任何特定的構(gòu)造函數(shù)因為它將被容器自動使用來實例化對象。
您還需要列出要在@EnableConfigurationProperties注釋中注冊的屬性類:
@Configuration
@EnableConfigurationProperties(FooProperties.class)
public class MyConfiguration {
}
注意:
當(dāng)@ConfigurationProperties bean以這種方式注冊時歹河,該bean將具有常規(guī)名稱:<prefix>-<fqn>掩浙,在@ConfigurationProperties注釋中指定的環(huán)境密鑰前綴<prefix>和bean的完全限定名稱<fqn>。如果注釋不提供任何前綴秸歧,則僅使用該bean的完全限定名稱厨姚。
上面示例中的bean名稱將是foo-com.example.FooProperties。
即使上述配置將為FooProperties創(chuàng)建一個常規(guī)bean键菱,我們建議@ConfigurationProperties僅通過Environment處理谬墙,特別是不從上下文中注入其他bean。話雖如此经备,@EnableConfigurationProperties注釋也會自動應(yīng)用于您的項目拭抬,以便使用@ConfigurationProperties注釋的所有現(xiàn)有bean都將從Environment配置。您可以通過確保FooProperties已經(jīng)是一個bean來快速上面的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可以為自己的密鑰提供自動完成的元數(shù)據(jù)文件。
1.7.1 第三方配置
除了使用@ConfigurationProperties來注釋類纷闺,還可以在public @Bean方法中使用它算凿。當(dāng)您希望將屬性綁定到不受控制的第三方組件時,這可能特別有用急但。
要從Environment屬性配置一個bean澎媒,請將@ConfigurationProperties添加到其Bean注冊中:
@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)和大寫(例如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)駝峰語法储玫。 |
person.first-name | 虛擬符號侍筛,推薦用于.properties和.yml文件。 |
person.first_name | 下劃線符號撒穷,用于.properties和.yml文件的替代格式匣椰。 |
PERSON_FIRST_NAME | 大寫格式。推薦使用系統(tǒng)環(huán)境變量時端礼。 |
1.7.3 屬性轉(zhuǎn)換
當(dāng)Spring綁定到@ConfigurationProperties bean時禽笑,Spring將嘗試將外部應(yīng)用程序?qū)傩詮?qiáng)制為正確的類型。如果需要自定義類型轉(zhuǎn)換蛤奥,您可以提供ConversionService bean(使用bean id conversionService)或自定義屬性編輯器(通過CustomEditorConfigurer bean)或自定義轉(zhuǎn)換器(使用注釋為@ConfigurationPropertiesBinding的bean定義)佳镜。
注意:
由于在應(yīng)用程序生命周期中早期請求了該bean,因此請確保限制ConversionService正在使用的依賴關(guān)系凡桥。通常蟀伸,您需要的任何依賴項可能在創(chuàng)建時可能未完全初始化。如果配置密鑰強(qiáng)制不需要缅刽,并且僅依賴使用@ConfigurationPropertiesBinding限定的自定義轉(zhuǎn)換器啊掏,則可能需要重命名自定義ConversionService。
1.7.4 @ConfigurationProperties驗證
Spring引導(dǎo)將嘗試使用Spring的@Validated注釋來注釋@ConfigurationProperties類衰猛。您可以直接在配置類上使用JSR-303 javax.validation約束注釋迟蜜。只需確保您的類路徑中符合JSR-303的實現(xiàn),然后在您的字段中添加約束注釋:
@ConfigurationProperties(prefix="foo")
@Validated
public class FooProperties {
@NotNull
private InetAddress remoteAddress;
// ... getters and setters
}
為了驗證嵌套屬性的值腕侄,您必須將關(guān)聯(lián)字段注釋為@Valid以觸發(fā)其驗證小泉。例如,基于上述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
}
}
您還可以通過創(chuàng)建名為configurationPropertiesValidator的bean定義來添加自定義的Spring Validator冕杠。 @Bean方法應(yīng)該聲明為靜態(tài)的。配置屬性驗證器是在應(yīng)用程序的生命周期早期創(chuàng)建的酸茴,并聲明@Bean方法分预,因為static允許創(chuàng)建bean,而無需實例化@Configuration類薪捍。這避免了早期實例化可能引起的任何問題笼痹。有一個屬性驗證樣本,所以你可以看到如何設(shè)置酪穿。
注意:
spring-boot-actuator模塊包括一個暴露所有@ConfigurationProperties bean的端點凳干。只需將您的Web瀏覽器指向/configprops或使用等效的JMX終結(jié)點。
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中只磷。還請注意经磅,由于@Value不支持輕松綁定泌绣,如果您需要使用環(huán)境變量提供該值,那么它不是一個很好的候選人预厌。最后阿迈,當(dāng)您可以在@Value中編寫一個SpEL表達(dá)式時,這些表達(dá)式不會從應(yīng)用程序?qū)傩晕募幚怼?/p>