利用 Spring Boot 中的 @ConfigurationProperties,优雅绑定配置参数


转载:程序员自由之路

 

使用 @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 中引入的。

img

参考#

作者:程序员自由之路

出处:https://www.cnblogs.com/54chensongxia/p/15250479.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM