轉載:程序員自由之路
使用 @Value("${property}") 注釋注入配置屬性有時會很麻煩,尤其是當你使用多個屬性或你的數據是分層的時候。
Spring Boot 引入了一個可替換的方案 —— @ConfigurationProperties 來注入屬性。
JavaBean 屬性綁定#
@Data @ConfigurationProperties("my.service") public class MyProperties { // 我們可以簡單地用一個值初始化一個字段來定義一個默認值 private boolean enabled = true; private InetAddress remoteAddress; private final Security security = new Security(); @Data public static class Security { private String username; private String password; // 如果這個屬性配置的話,默認是“USER” private List<String> roles = new ArrayList<>(Collections.singleton("USER")); } }
在配置文件中進行如下配置:
my: service: enabled: true remoteAddress: 127.0.0.1 security: username: csx password: passwoed roles: - role1 - role2
最后生成的 Bean 的屬性如下:
{
"enabled": true, "remoteAddress": "127.0.0.1", "security": { "username": "csx", "password": "passwoed", "roles": [ "role1", "role2" ] } }
以上的綁定當時需要提供默認的構造函數,以及get/setter方法。
並且不支持 JavaBean 中的靜態成員變量的數據綁定
另外,@ConfigurationProperties 還有兩個其他屬性。
@ConfigurationProperties( value = "my.service", ignoreInvalidFields = false, ignoreUnknownFields = false)
ignoreInvalidFields:是否忽略非法值,比如將一個字符串 “foo” 賦值給 bool 值,不忽略的話會報啟動異常。
ignoreUnknownFields:對於多余的配置是否會報異常。
構造函數綁定#
有些情況下,我們需要綁定的 JavaBean 是不可變的(防止配置注入 Bean 以后,開發者在程序中錯誤地將配置改掉了)。這種情況下我們可以使用構造函數形式的綁定,只提供 getter 方法。
@Getter @ConstructorBinding @ConfigurationProperties("my.service") public class MyProperties { private boolean enabled; private InetAddress remoteAddress; private final Security security; public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) { this.enabled = enabled; this.remoteAddress = remoteAddress; this.security = security; } @Getter public static class Security { private String username; private String password; private List<String> roles; public Security(String username, String password, @DefaultValue("USER") List<String> roles) { this.username = username; this.password = password; this.roles = roles; } } }
@DefaultValue 可以指定默認值。
使用構造函數綁定的方式,只能 @EnableConfigurationProperties 或者 @ConfigurationPropertiesScan 的方式激活 Bean。而不能使用 @Component、@Bean 或者 @Import 的方式進行數據綁定。
如果你的類有多個構造函數,可以直接指定使用哪個。
@ConstructorBinding public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) { this.enabled = enabled; this.remoteAddress = remoteAddress; this.security = security; }
激活方式#
方式一:添加 @Component 注解
上面的方式需要保證 MyProperties 能被 Spring 掃到。
@Data @Component @ConfigurationProperties("my.service") public class MyProperties { }
方式二:通過 @Bean 方法
@Configuration public class ServiceConfig { @Bean public MyProperties myProperties(){ return new MyProperties(); } }
方式三:@EnableConfigurationProperties(推薦)
@Configuration @EnableConfigurationProperties(MyProperties.class) public class ServiceConfig { }
方式四:@ConfigurationPropertiesScan
@SpringBootApplication @ConfigurationPropertiesScan({ "com.example.app", "com.example.another" }) public class MyApplication { }
怎么使用#
我們通過配置在 Spring 容器中生成了配置 Bean,那么需要怎么使用他們呢?
@Service public class MyService { // 依賴注入 @Autowired private MyProperties properties; public void service(){ System.out.println(properties.getRemoteAddress()); } } @Service public class MyService { private MyProperties properties; // 通過構造函數注入,一般推薦這種方式 public MyService(MyProperties properties) { this.properties = properties; } public void service(){ System.out.println(properties.getRemoteAddress()); } }
給第三方類綁定值#
假如某些類不是你自己開發的,你也想使用 @ConfigurationProperties 的方式給他綁定值,那么可以進行下面的方式進行配置。
@Configuration(proxyBeanMethods = false) public class ThirdPartyConfiguration { @Bean @ConfigurationProperties(prefix = "another") public AnotherComponent anotherComponent() { return new AnotherComponent(); } }
寬松綁定原則(Relaxed Binding)#
所謂的寬松綁定原則是指:並不是 JavaBean 中的屬性必須要和配置文件中的一致才能綁定數據,context-path 也能綁定到 contextPath 屬性上。下面舉個列子:
@ConfigurationProperties(prefix = "my.main-project.person") public class MyPersonProperties { private String firstName; public String getFirstName() { return this.firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } }
下面的幾種方式,都能將配置文件或者環境變量中的值綁定到 firstName 上。
形式 | 使用場景 |
---|---|
my.main-project.person.first-name |
推薦使用在 .properties and .yml files. |
my.main-project.person.firstName |
Standard camel case syntax. |
my.main-project.person.first_name |
推薦使用在 .properties and .yml files. |
MY_MAINPROJECT_PERSON_FIRSTNAME |
推薦使用在系統環境變量讀取配置時使用 |
和 @Value 對比#
@Value 是 Spring Framework 中的注解,而 @ConfigurationProperties 是在 Spring Boot 中引入的。
參考#
作者:程序員自由之路
出處:https://www.cnblogs.com/54chensongxia/p/15250479.html
版權:本作品采用「署名-非商業性使用-相同方式共享 4.0 國際」許可協議進行許可。