Spring Boot 基础: 使用 @ConfigurationProperties
实现自定义配置属性的自动装配
文章目录
- Spring Boot 基础: 使用 `@ConfigurationProperties` 实现自定义配置属性的自动装配
- 简介
- 参考
- 正文
- 提前预览
- `@Value`
- `@ConfigurationProperties`
- `@EnableConfigurationProperties`
- `spring-boot-configuration-processor`
- 完整代码示例
- 结语
简介
在 Spring Boot 的实践中我们有时会需要针对整个项目进行全局配置,可能是应用的部署信息、依赖配置信息,甚至是服务需要的全局参数等。通常我们都会将配置信息写在 resources/application.yml(或是 .properties)
内,接下来我们可以透过几种手段来提取配置信息,接下来让我娓娓道来。
参考
SPRINGBOOT用@CONFIGURATIONPROPERTIES获取配置文件值 | |
Spring Boot 配置文件注入,在yml中可以自动提示 | |
SPRINGBOOT项目启动成功后执行一段代码的两种方式 | |
Spring Boot中自定义属性的代码完成 | https://www.mdoninger.de/2015/05/16/completion-for-custom-properties-in-spring-boot.html |
正文
提前预览
首先我们先预览下面提到的各个注解或依赖的作用:
-
@Value
引入单个配置属性值 -
@ConfigurationProperties
声明配置属性的映射类型 -
@EnableConfigurationProperties
允许挂载配置对象,同时也是配置对象注册 Bean 的入口 -
spring-boot-configuration-processor
自动生成配置属性说明文件,提供编程时的代码提示
@Value
首先我们第一个想到的方法是使用 @Value("${xxx}")
注解来获取配置文件的配置项,使用示例如下:
application.yml
server:
port: 8800
DemoController.java
@RestController
class DemoController {
@Value("${server.port}")
private Integer port;
@GetMapping("/")
public String info() {
return "Default route from localhost:" + port;
}
}
这样一来我们就完成配置项的引入,但是如果需要配置的项目越来越多结构越来越复杂呢?还要像这样一个个引入吗?
application.yml
my:
prop:
name: superfree
port: 8800
exclude-users:
- user1
- user2
- user3
server:
name: my-server
url: http://localhost:8801
client:
name: my-client
url: http://localhost:8802
DemoController.java
@RestController
class DemoController {
@Value("${my.prop.name}")
private String name;
@Value("${my.prop.port}")
private Integer port;
@Value("${my.prop.exclude-users}")
private List<String> excludeUsers;
@Value("${my.prop.server.name}")
private String serverName;
@Value("${my.prop.server.url}")
private String serverUrl;
@Value("${my.prop.client.name}")
private String clientName;
@Value("${my.prop.client.url}")
private String clientUrl;
// ...
}
难不成要像这样一个个引入吗?这样也太丑而且有够麻烦hhh,所以通常我们选择采取另一个做法
@ConfigurationProperties
@ConfigurationProperties
这个注解可以声明一个配置属性对应的类型,然后我们就可以使用自动装配的功能,声明方式如下:
application.yml:配置项结构
my:
prop:
name: superfree
port: 8800
MyProperties.java
// 透过 prefix 参数声明前缀
@ConfigurationProperties(prefix = "my.prop")
public class MyProperties {
// 与配置文件属性一一对应
private String name;
private Integer port;
// getter/setter for name & port
}
@EnableConfigurationProperties
配置文件和映射类型都写好了,接下来我们必须找到一个装配该类型的地方。
一种方法是将该配置类加上 @Component
,作为一个"组件"注入
@Component // 声明为独立的组件
@ConfigurationProperties(prefix = "my.prop")
public class MyProperties {
// ...
第二种做法是使用 @EnableConfigurationProperties
将配置类挂载到我们要使用的类上,而这个类通常可以是某个配置类或是其他组件(Component)
@Configuration // or @Component
@EnableConfigurationProperties(MyProperties.class)
public class MyConfig {
// 使用 EnableConfigurationProperties 之后就可以透过 @Autowired 实现自动装配
@Autowired
private MyProperties myProperties;
// ...
or
@RestController
@EnableConfigurationProperties(MyProperties.class)
public class DemoController {
@Autowired
private MyProperties myProperties;
// ...
透过这种方式我们就可以借由声明配置项的映射类型即可实现自动装配,非常便利。
spring-boot-configuration-processor
最后一件事情是,如果我们的服务被打包成第三方依赖,或是本身开发过程中,我们可能希望 IDE 能更智能的根据映射对象来提示我们到底该配置哪些属性,我们就可以用上 spring-boot-configuration-processor
依赖,在 maven 添加下方依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
这时候我们再手动的调用 mvn clean package
(IDEA 有提供可视化按钮直接使用),我们就会在打包后的 target 项目中看到关于配置项的结构说明文件 spring-configuration-metadata.json
这样一来使用我们的包作为依赖的开发者,他的 IDE 就能够根据这个文件在 yml 中给出相应的代码提示。
若我们想要在自己开发的过程中也享受到代码提示我们可以选择将 META-INF
目录整个复制到 resoureces 目录之下(如下图),即可实现相同效果
完整代码示例
最后我们给出完整示例的关键代码,详细完整项目在这里
application.yml:配置项目(实现嵌套对象配置)
my:
prop:
name: superfree
port: 8800
exclude-users:
- user1
- user2
- user3
server:
name: my-server
url: http://localhost:8801
client:
name: my-client
url: http://localhost:8802
MyProperties.java:配置项类型
@ConfigurationProperties(prefix = "my.prop")
public class MyProperties {
private String name;
private Integer port;
private List<String> excludeUsers;
private ServerProperties server;
private ClientProperties client;
// toString, getter/setter
}
ServerProperties.java:嵌套类型1
// 注意,这边就不需要 ConfigurationProperties 了
public class ServerProperties {
private String name;
private String url;
// toString, getter/setter
}
ClientProperties.java:嵌套类型2
public class ClientProperties {
private String name;
private String url;
// toString, getter/setter
}
Runner.java:测试类
@Component
@EnableConfigurationProperties(MyProperties.class)
public class Runner implements ApplicationRunner {
@Autowired
private MyProperties myProperties; // 自动装配配置项
@Override
public void run(ApplicationArguments args) throws Exception {
show();
}
public void show() {
System.out.println("----- show my.prop -----");
System.out.println(myProperties);
}
}
输出
----- show my.prop -----
MyProperties{name='superfree', port=8800, excludeUsers=[user1, user2, user3], server=ServerProperties{name='my-server', url='http://localhost:8801'}, client=ClientProperties{name='my-client', url='http://localhost:8802'}}
结语
好啦到此结束啦,大家都学会如何优雅的引入配置文件的内容了吗,再也不用看到一大票丑丑的 @Value
了。