前言
在使用SpringBoot的过程中, 总免不了的是其相关配置文件的使用. 我们可以通过, @ConfigurationProperties
和@Value
标签将applicaiton.properties
配置内容注入. 也可以通过Environment
对象实时获取. 如下即介绍一下这几种使用方式的优缺点和基本实现.
前置
- pom.xml
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<springboot.version>2.3.12.RELEASE</springboot.version>
<lombock.version>1.18.12</lombock.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
笔者这边使用父子maven项目的模式. 相关版本还请各位读者自己维护一下。
- application.yml
server:
port: 8080
servlet:
context-path: /arsenal-springboot
config:
env:
name: hello
age: 18
本次我们只配置通用的配置文件. 不考虑prefix等场景.
标签配置-实战
@Value标签
- 源码定义
package org.springframework.beans.factory.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value();
}
根据@value
标签的定义可知, 其可以配置在FIELD
/METHOD
/PARAMETER
/ANNOTATION_TYPE
上面.
- 测试配置
package com.yanxml.arsenal.springboot.env.config.value;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Data
public class StuValue {
public final static String BEAN_NAME = "StuValue";
@Value("${config.env.name}")
private String name;
@Value("${config.env.age}")
private Integer age;
}
此处使用绑定属性的方式.
- 测试获取
@RestController
@RequestMapping(value = "env")
public class EnvController {
@Autowired
private StuValue stuValue;
@RequestMapping(value = "stuValue", method = RequestMethod.GET)
@ResponseBody
public Object getStuValue(){
return stuValue;
}
}
@ConfigurationProperties 标签
package org.springframework.boot.context.properties;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Indexed;
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Indexed
public @interface ConfigurationProperties {
@AliasFor("prefix")
String value() default "";
@AliasFor("value")
String prefix() default "";
boolean ignoreInvalidFields() default false;
boolean ignoreUnknownFields() default true;
}
- 测试用例
package com.yanxml.arsenal.springboot.env.config.configuration;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "config.env")
@Data
public class StuConfiguration {
public final static String BEAN_NAME = "StuConfiguration";
private String name;
private Integer age;
}
此处值得注意的是@ConfigurationProperties
需要和@Component
标签一同使用.
@RestController
@RequestMapping(value = "env")
public class EnvController {
@Autowired
private StuConfiguration stuConfiguration;
@ResponseBody
@RequestMapping(value = "stuConfiguration", method = RequestMethod.GET)
public Object getStuConfiguration(){
return stuConfiguration;
}
}
Environment实时获取
如果我们看过Spring的装载过程, 即可知道. Spring在装载时, 获取环境变量和相关配置文件, 并且将其放入Environment对象内. 我们可以通过get()
方法获取其中的各个对象.
- 测试用例 - StuEnv
package com.yanxml.arsenal.springboot.env.config.environment;
import lombok.Data;
@Data
public class StuEnv {
public final static String BEAN_NAME = "StuEnv";
private String name;
private Integer age;
}
- 测试用例 - StuEnvConfig
package com.yanxml.arsenal.springboot.env.config.environment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@Component
public class StuEnvConfig {
@Autowired
private Environment environment;
@Bean
public StuEnv generateStuEnv(){
StuEnv stuEnv = new StuEnv();
stuEnv.setName(environment.getProperty("config.env.name"));
stuEnv.setAge(Integer.valueOf(environment.getProperty("config.env.age")));
return stuEnv;
}
}
此处值得注意的是, @Bean
标签修饰的方法, 需要是一个public类型的方法.
- 测试用例 - controller
@RestController
@RequestMapping(value = "env")
public class EnvController {
@Autowired
private StuEnv stuEnv;
@RequestMapping(value = "stuEnv", method = RequestMethod.GET)
@ResponseBody
public Object getStuEnv(){
return stuEnv;
}
}
配置文件注意事项1 - prefix前缀
配置文件注意事项2 - 配置文件的指定优先级 & 如何运行时强行指定
@ConfigurationProperties装配原理和自定义实现
TODO 敬请期待下一篇博客.
Reference
[1] @ConfigurationProperties使用详解
[2] (Offical)(2.3.12.RELEASE)configuration-metadata-annotation-processor