Spring @ConfigurationProperties —— 从配置原理到手把手带你实现「指定前缀」获取属性
2023-12-11 12:23:08
在这个快节奏、敏捷迭代的时代,Spring已经成为Java编程领域不可忽视的“香饽饽”。从接触它开始,就伴随着我们进行项目开发。而在使用它的过程中,我们经常会遇到需要从配置文件中获取配置属性的情况。例如:
- 当发送电子邮件时,我们需要获取收发件人及邮件服务器的地址和端口号。
- 当访问数据库时,我们需要获取数据库的URL、用户名和密码。
对于上述这些常见的需求,Spring框架早已贴心地为我们准备好了@ConfigurationProperties,如此一来就可以直接通过代码来获取配置属性,这样无疑就减少了很大的人工操作和程序的冗余度。这岂不妙哉?那么,我们马上开始吧!
一切从最简单的开始:聊一聊 @ConfigurationProperties 的原理
直奔主题:所谓@ConfigurationProperties,其实就是通过在你的 JavaBean 上添加此注解,允许你将配置属性绑定到你 Bean 的字段上。这么说可能太理论化了,先抛出一个灵魂拷问:“如果你是 @ConfigurationProperties,那么你将完成怎样的工作呢?”
public class MyBean {
private String name;
private int age;
// 填写 @ConfigurationProperties 注解,指定其前缀为 "mybean"
@ConfigurationProperties(prefix = "mybean")
// 获取或设置 name
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 获取或设置 age
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
所以@ConfigurationProperties 所做的工作就是:根据你配置的前缀,从 配置文件(此处特指 application.properties 和 application.yml)或环境变量中找到相应的前缀,并且将找到的值赋给你的 JavaBean 的字段。
【手把手教学环节】如何使用 Spring Boot 优雅获取配置属性
搭建好环境之后,我们就开始撸代码吧。话不多说,直接放代码!
1. 配置配置文件
首先,我们需要在配置文件中定义一些配置属性:
# application.yml
mybean:
name: 小明
age: 18
2. 新建一个 JavaBean
@ConfigurationProperties(prefix = "mybean")
public class MyBean {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "MyBean{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
3. 注册 Bean
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public MyBean myBean() {
return new MyBean();
}
}
4. 获取配置属性
现在,我们就可以通过以下方式获取配置属性:
@Autowired
private MyBean myBean;
public static void main(String[] args) {
// 输出 myBean 的值
System.out.println(myBean);
}
输出结果:
MyBean{name='小明', age=18}
至此,我们已经成功地使用了 Spring Boot 来获取配置属性。
核心揭秘:源代码 带你探秘 ConfigurationProperties
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationProperties {
/**
* The prefix that properties will match if specified.
* <p>Default is an empty string: "", which matches any property.
* @return the prefix string
*/
String prefix() default "";
/**
* Whether to ignore unknown properties.
* <p>Default is {@code true}.
* @return {@code true} if unknown properties should be ignored
*/
boolean ignoreUnknownFields() default true;
/**
* Whether to ignore invalid properties.
* <p>Default is {@code false}.
* @return {@code true} if invalid properties should be ignored
* @since 2.1
*/
boolean ignoreInvalidFields() default false;
/**
* The placeholders to resolve in ${...} expressions within
* the configuration properties.
* <p>Default is to resolve placeholders against system properties,
* environment variables and Spring's {@link PropertySources}.
* @return the list of placeholder resolvers
* @since 2.2
*/
PlaceholderResolver[] resolvers() default {};
}
从源码中可以看出,@ConfigurationProperties 注解有三个主要参数:
- prefix: 指定属性的前缀,如果不指定,则匹配所有属性。
- ignoreUnknownFields: 是否忽略未知属性,默认值为 true。
- ignoreInvalidFields: 是否忽略无效属性,默认值为 false。
我们还能做出哪些扩展?
1. 自定义 Bean 注解
有时候,我们希望通过自定义注解来达到同样的效果,这该如何实现呢?此时,我们可以使用 @PropertySource 注解来实现:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@PropertySource("classpath:my-properties.properties")
public @interface MyProperties {
String prefix() default "";
boolean ignoreUnknownFields() default true;
boolean ignoreInvalidFields() default false;
}
2. 自定义属性转换器
在有些情况下,我们可能需要对属性进行一些转换,比如将字符串转换为日期或数字。我们可以使用 @ConfigurationPropertiesBinding 注解来实现:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationPropertiesBinding {
Class<? extends PropertySourcesPropertyResolver> resolver() default PropertySourcesPropertyResolver.class;
boolean ignoreInvalidFields() default false;
boolean ignoreNestedProperties() default false;
}
上面简单举了几个例子,如果你有更多的创意,可以进一步去探索。Spring Boot 中的很多功能都是基于扩展实现的,如果你能熟练掌握这些扩展方式,那么恭喜你,你已经在 Spring Boot 的道路上迈出了一大步!
最后结语:不忘总结,牢记于心
- @ConfigurationProperties 注解用于从配置文件或环境变量中获取配置属性。
- @ConfigurationProperties 注解有三个主要参数:prefix、ignoreUnknownFields 和 ignoreInvalidFields。
- 我们还可以通过自定义 Bean 注解或自定义属性转换器来扩展 @ConfigurationProperties 注解的功能。