在项目的许多开发场景下,为了提高的可维护性,通过会将一些属性参数配置于项目的 YML
文件中, Spring
中一共提供两种方式用于读取配置文件中的数据,下面将分别展开介绍。
一、@Value
1. 基础配置
当我们将一些参数配置在项目配置文件中时,即可通过 @Value
注解获取值。
如在 application.yml
中添加如下配置:
info:
msg1: 123
msg2: 456
在代码中获取参数方式如下:
public class MyTest {
@Value("${info.msg1}")
private String msg1;
@Value("${info.msg2}")
private String msg2;
public void demo() {
// 打印 123
System.out.println(msg1);
// 打印 456
System.out.println(msg2);
}
}
2. 默认填充
但如果设置了配置文件中不存的值时很显然在读取时会出现空值异常,因此我们也可以根据需要配置默认值。
public class MyTest {
// 设置默认值为 123
@Value("${info.msg1:123}")
private String msg1;
// 设置默认值为 456
@Value("${info.msg2:456}")
private String msg2;
}
3. 配置应用
在通过 @Value
获取配置信息时,若需要在类成员变量中直接使用是无法正常读取数据。
如下述示例中即便 YML
文件配置了 latch.size
的值,在初始化 latch
读取的 size
仍然为 int
默认初始化值 0
。
public class TestService {
@Value("${latch.size}")
private int size;
// size 无法读取,仍为 0
public CountDownLatch latch = new CountDownLatch(size);
}
因此,在使用 @Value
若搭配成员变量时,可以通过实现 InitializingBean
的 afterPropertiesSet()
设置读取的值,其会在 Spring
容器首次初始化 Bean
对象时触发。
public class TestService implements InitializingBean {
@Value("${latch.size}")
private int size;
public CountDownLatch latch = new CountDownLatch(0);
public void afterPropertiesSet() throws Exception {
latch = new CountDownLatch(size);
}
}
4. 文件读取
在 Spring
中提供了 Resource
类可用于读取 resources
目录下的资源文件,搭配 @Value
注解即可实现动态的文件读取。
其中 classpath
即相当于 resources
目录层级,如在项目的 resources
目录下存在文件 files/hello.txt
,即可通过 @Value("classpath:files/hello.txt")
获取资源文件。在获取资源对象文件后,若需要初始化 File
对象可通过 getURI()
获取 URI
对象,对于其它操作推荐 getInputStream()
获取数据流对象进行管理。
@Component
public class FileComponent {
@Value("classpath:files/hello.txt")
private Resource txtResource;
@Value("classpath:files/hello.json")
private Resource jsonResource;
@Autowired
private ObjectMapper objectMapper;
public void read1() {
// 通过 URI 初始化文件
File file = new File(txtResource.getURI());
}
public void read2() {
// 获取文件 IO 流
try (InputStream inputStream = jsonResource.getInputStream()) {
JsonNode node = objectMapper.readTree(inputStream);
} catch (IOException e){
throw new RuntimeException(e);
}
}
}
二、@ConfigurationProperties
1. 基础配置
上面介绍了使用 @Value
获取配置文件参数,但如果需要获取大量的参数时重复的前缀显然有些冗余, @ConfigurationProperties
即用于解决此类情况。
ibudai:
info:
msg1: 111
msg2: 222
msg3: 333
msg4: 444
(1) 方式一
需要注意的一点是类中的变量名必须和配置文件中的名字一致,且每个变量必须有 set
方法,这个我用 @Data
自动提供。
@Data
@Component
@ConfigurationProperties(prefix = "ibudai.info")
public class TestEntity {
private String msg1;
private String msg2;
private String msg3;
private String msg4;
}
(2) 方式二
和方式一不同的是类上无需使用 @Component
注解,而是交给 Spring Boot
自动管理,即在项目启动类上添加注解 @EnableConfigurationProperties
。
// 测试类
@Data
@ConfigurationProperties(prefix = "ibudai.info")
public class TestEntity {
private String msg1;
private String msg2;
private String msg3;
private String msg4;
}
// 项目启动类
@SpringBootApplication
@EnableConfigurationProperties
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2. 默认填充
与 @Value
类似,@ConfigurationProperties
也可为参数设置默认值。
即为成员变量直接赋值,若 YML
中不存在对应配置时则读取变量赋值,否则读取配置文件值。
// 测试类
@Data
@ConfigurationProperties(prefix = "ibudai.info")
public class TestEntity {
private String msg1 = "111";
private String msg2 = "222";
private String msg3 = "333";
private String msg4 = "444";
}
3. 配置应用
完成属性注入之后即可直接在项目中通过 @Autowired
注解获取属性值。
@Service
public class TestService {
@Autowired
private TestEntity testEntity;
public void test() {
System.out.println(testEntity.getMsg1());
System.out.println(testEntity.getMsg2());
System.out.println(testEntity.getMsg3());
System.out.println(testEntity.getMsg4());
}
}