1. 前言
在Spring Boot項目中我們經常需要讀取application.yml配置文件的自定義配置,今天就來羅列一下從yaml讀取配置文件的一些常用手段和方法。
2. 使用@Value注解
首先,會想到使用@Value注解,該注解只能去解析yaml文件中的簡單類型,並綁定到對象屬性中去。
felord:
phone: 182******32
def:
name: 碼農小胖哥
blog: felord.cn
we-chat: MSW_623
dev:
name: 碼農小胖哥
blog: felord.cn
we-chat: MSW_623
type: JUEJIN
對於上面的yaml配置,如果我們使用@Value注解的話,冒號后面直接有值的key才能正確注入對應的值。例如felord.phone我們可以通過@Value獲取,但是felord.def不行,因為felord.def后面沒有直接的值,它還有下一級選項。另外@Value不支持yaml松散綁定語法,也就是說felord.def.weChat獲取不到felord.def.we-chat的值。
@Value是通過使用Spring的SpEL表達式來獲取對應的值的:
// 獲取 yaml 中 felord.phone的值 並提供默認值 UNKNOWN
@Value("${felord.phone:UNKNOWN}")
private String phone;
@Value的使用場景是只需要獲取配置文件中的某項值的情況下,如果我們需要將一個系列的值進行綁定注入就建議使用復雜對象的形式進行注入了。
3. 使用@ConfigurationProperties注解
@ConfigurationProperties注解提供了我們將多個配置選項注入復雜對象的能力。它要求我們指定配置的共同前綴。比如我們要綁定felord.def下的所有配置項:
package cn.felord.yaml.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static cn.felord.yaml.properties.FelordDefProperties.PREFIX;
/**
* @author felord.cn
*/
@Data
@ConfigurationProperties(PREFIX)
public class FelordDefProperties {
static final String PREFIX = "felord.def";
private String name;
private String blog;
private String weChat;
}
我們注意到我們可以使用
we-chat的值,因為這種形式支持從駝峰camel-case到短橫分隔命名kebab-case的自動轉換。
如果我們使用@ConfigurationProperties的話建議配置類命名后綴為Properties,比如Redis的后綴就是RedisProperties,RabbitMQ的為RabbitProperties。
另外我們如果想進行嵌套的話可以借助於@NestedConfigurationProperty注解實現。也可以借助於內部類。這里用內部類實現將開頭yaml中所有的屬性進行注入:
package cn.felord.yaml.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import static cn.felord.yaml.properties.FelordProperties.PREFIX;
/**
* 內部類和枚舉配置.
*
* @author felord.cn
*/
@Data
@ConfigurationProperties(PREFIX)
public class FelordProperties {
static final String PREFIX = "felord";
private Def def;
private Dev dev;
private Type type;
@Data
public static class Def {
private String name;
private String blog;
private String weChat;
}
@Data
public static class Dev {
private String name;
private String blog;
private String weChat;
}
public enum Type {
JUEJIN,
SF,
OSC,
CSDN
}
}
單獨使用@ConfigurationProperties的話依然無法直接使用配置對象FelordDefProperties,因為它並沒有被注冊為Spring Bean。我們可以通過兩種方式來使得它生效。
3.1 顯式注入Spring IoC
你可以使用@Component、@Configuration等注解將FelordDefProperties注入Spring IoC使之生效。
package cn.felord.yaml.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import static cn.felord.yaml.properties.FelordDefProperties.PREFIX;
/**
* 顯式注入Spring IoC
* @author felord.cn
*/
@Data
@Component
@ConfigurationProperties(PREFIX)
public class FelordDefProperties {
static final String PREFIX = "felord.def";
private String name;
private String blog;
private String weChat;
}
3.2 使用@EnableConfigurationProperties注冊
我們還可以使用注解@EnableConfigurationProperties進行注冊,這樣就不需要顯式聲明配置類為Spring Bean了。
package cn.felord.yaml.configuration;
import cn.felord.yaml.properties.FelordDevProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 使用 {@link EnableConfigurationProperties} 注冊 {@link FelordDevProperties}使之生效
* @author felord.cn
*/
@EnableConfigurationProperties({FelordDevProperties.class})
@Configuration
public class FelordConfiguration {
}
該注解需要顯式的注冊對應的配置類。
3.3 使用@ConfigurationPropertiesScan掃描
在Spring Boot 2.2.0.RELEASE中提供了一個掃描注解@ConfigurationPropertiesScan。它可以掃描特定包下所有的被@ConfigurationProperties標記的配置類,並將它們進行IoC注入。
package cn.felord.yaml;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
/**
* {@link ConfigurationPropertiesScan} 同 {@link EnableConfigurationProperties} 二選一
*
* @see cn.felord.yaml.configuration.FelordConfiguration
* @author felord.cn
*/
@ConfigurationPropertiesScan
@SpringBootApplication
public class SpringBootYamlApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootYamlApplication.class, args);
}
}
這非常適合自動注入和批量注入配置類的場景,但是有版本限制,必須在2.2.0及以上。
3.4 Environment
Spring Boot項目的話也可以通過org.springframework.core.env.Environment 提供的getProperty(String key)來獲取,一般並不是很常用。
4. 總結
日常開發中單個屬性推薦使用@Value,如果同一組屬性為多個則推薦@ConfigurationProperties。需要補充一點的是@ConfigurationProperties還支持使用JSR303進行屬性校驗。多多關注:碼農小胖哥 獲取更多的技術干貨。相關的demo 可通過公眾號回復yaml獲取。
關注公眾號:Felordcn 獲取更多資訊
