SpringBoot中配置文件优先级和有哪些方式获取配置文件中的信息
一、SpringBoot中配置文件的优先级
1、file: ./config/ (./ 表示当前路径下 file表示是当前项目)
2、file: ./
3、classpath:config/
4、classpath:
从上到下,优先级依次递减!
各配置文件之间的特性:
①: 如果配置相同的东西 如:server.port ,高优先级的文件中的配置会覆盖低优先级的文件中的配置。
②: 各文件之间是互补配置的。
参考类: ConfigFileApplicationListener
二、有哪些方式获取配置文件中的信息?
1、获取application.properties(application.yml)中的配置信息
①:通过@ConfigurationProperties 注解来获取
接口定义:
@Target({ ElementType.TYPE, ElementType.METHOD }) // 可以作用在类和方法上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConfigurationProperties {
@AliasFor("prefix")
String value() default ""; // 表示前缀
@AliasFor("value")
String prefix() default ""; // 表示前缀
boolean ignoreInvalidFields() default false;
boolean ignoreUnknownFields() default true;
}
使用方式:
@ConfigurationProperties(prefix = "dog") // 指定前缀
@Component
public class Dog {
private String name; // 自动绑定
private int age;
// 需要 对应的 setter 方法
}
配置文件信息:
dog.name=dog
dog.age=11
②:通过@Value注解来获取(value可以通过${}获取环境变量中的属性,#{}SPEL)
接口定义:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.ANNOTATION_TYPE}) // 可以作用在 字段、方法、参数、注解 上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Value {
String value();
}
使用方式:
@Component
public class Dog {
@Value("${dog.name}")
private String name;
@Value("${dog.age}")
private int age;
}
配置文件信息:
dog.name=dog
dog.age=11
2、获取自定义配置文件(properties文件)中的配置信息
2.1、想要获取自定义配置文件(properties文件)中的配置信息,我们必须先加载该配置文件,通过@PropertySource注解加载
接口定义:
@Target(ElementType.TYPE) // 只能作用在类上
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
String name() default ""; // 表明属性资源的名称
String[] value(); // 资源文件的路径 classpath:下
boolean ignoreResourceNotFound() default false; // 不 忽略没有找到的资源
String encoding() default "";
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
@PropertySource注解的使用
2.2、在加载配置文件过后
①: 通过@ConfigurationProperties 注解来获取
@Component
@ConfigurationProperties(prefix = "cat") // 指明加载配置文件的前缀
@PropertySource(value={"classpath:cat.properties"}) // 加载自定义配置文件
public class Cat {
②: 通过@Value 注解获取
@Component
@PropertySource(value={"classpath:cat.properties"})
public class Cat {
@Value("${cat.name}")
private String name;
@Value("${cat.age}")
private int age;
注意:
1、当同时通过 @ConfigurationProperties 和 @Value 去获取配置信息时: @ConfigurationProperties 生效
2、当application.properties和自定义配置文件冲突时,application.properties 生效
3、无论是application.properties,还是自定义的配置文件,在加载后,都会存放到环境对象(Environment)中去,我们也可以从环境对象中获取配置信息
public class Cat implements EnvironmentAware{
private Environment environment;
/**
* 实现 EnvironmentAware 接口,可以在 IOC创建好该 Cat对象后,自动注入 Environment对象到该cat对象中
* 于是我们可以通过操作 Environment 获取信息
* @param environment
*/
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
}
4、@Value 底层不依赖 setter方法和构造器,而@ConfigurationProperties底层依赖setter方法(没有对应的setter方法会赋值失败)
特性: @Value获取值和@ConfigurationProperties获取值比较
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定(松散语法) | 支持 | 不支持 |
SpEL #{11*2} | 不支持 | 支持 |
JSR303数据校验 @Validated | 支持 | 不支持 |
复杂类型封装(对象,list,set,map,数组) | 支持 | 不支持 |
3、可以通过@ImportResource导入xml配置文件
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE) // 作用在类上
@Documented
public @interface ImportResource {
@AliasFor("locations")
String[] value() default {}; // 指定本地的xml配置文件的路径
@AliasFor("value")
String[] locations() default {}; // 指定本地的xml配置文件的路径
Class<? extends BeanDefinitionReader> reader() default BeanDefinitionReader.class;
}
使用方式
@ImportResource(locations = {"classpath:bean.xml","classpath:spring.xml"})
public class Person {
}
4、针对于属性为 static 、static final 、 final 的配置
1: 针对于 static 修饰的属性
static 的作用
1、static可以修饰 属性(成员变量),方法,内部类,代码块(静态代码块),还可以 静态导入。
2、static修饰的属性和方法只有一份,是属于类的,而不是对象,可以通过类名直接调用。
3、对象严格意义上是不能调用 静态方法和 静态属性的。但是我们可以通过对象调用,但不推荐。
4、静态方法不存在继承这一说法。
5、静态属性在类加载的准备阶段分配空间,并赋予默认值(比如:int 默认为 0 ,boolean 默认为 false),然后在初始化阶段赋值(如:private static int a = 10,这里的赋值就会执行a=10这个操作)和执行静态代码块。
6、static方法 只能使用static属性,调用static方法;普通方法既可以使用static属性和普通属性又可以调用static方法和普通方法
通过@Value 给静态变量赋值
@Component
public class Pig {
// @Value("pig.name") 直接这样会赋值失败
private static String name;
@Value("${pig.name}") // 通过作用在方法的方式将值赋给 静态属性
public void setName(String name){
Pig.name = name;
}
}
通过@ConfigurationProperties 给静态变量赋值
@ConfigurationProperties(prefix = "pig")
@Component
public class Pig {
private static String name;
/**
* 因为 @ConfigurationProperties底层依赖属性的setter方法(非静态的,如果是静态的setter方法,就会 赋值失败)
*
* 我们可以定义如下方法,来绕开static 给我们的限制
*/
public void setName(String name){
Pig.name = name;
}
}
2: 针对于 final 修饰的属性
final 的作用
1、final 可以用来修饰 {属性(成员变量)、参数、局部变量}(不可改变,对于基本类型,值不能改变;对于引用类型,地址不能改变)、方法(不可被重写)、类(不可被继承)
2、final 修饰的属性
定义时就赋值
所有构造器中给该变量赋值
代码块中给变量赋值
无法通过@ConfigurationProperties给 final 修饰的变量 (常量) 赋值,因为 @ConfigurationProperties底层依赖setter方法,而常量不能通过setter方法设置值。
通过 @Value 给 常量 赋值 (这是一种取巧的方式)
// 通过构造器 给 类中的 常量赋值 --这是OK的
public class Tiger {
private final String name;
public Tiger(String name){
this.name = name;
}
}
自定义一个java配置类
@Configuration
public class MyConfig {
/**
* 通过@Value 作用在参数上(也可作用在方法上),去获取环境变量中的配置信息
* 显示的调用 Tiger 中的 有参构造器,
*/
@Bean
public Tiger tiger(@Value("${tiger.name}") String name){
return new Tiger(name);
}
}
3: 针对于 static final 修饰的属性
不能通过@ConfigurationProperties 和 @Value 赋值, static final 修饰的变量,只能 定义时赋值 和 静态代码块中赋值
5、如果同时出现 静态属性 、常量属性 和 普通属性,我们也可以通过@Value 或者 @Value+ @ConfigurationProperties 来获取资源并赋值
1、只通过@Value 的方法
类信息:
public class Lion {
private final String name; // 常量属性
private static int age; // 静态属性
private String email; // 普通属性
public Lion(String name,int age,String email){
this.name =name;
this.email =email;
Lion.age = age;
}
}
配置信息:
@Configuration
public class MyConfig {
// 通过 @Value 去环境对象中获取 配置信息,并赋给形参
@Bean
public Lion lion(@Value("${lion.name}") String name,@Value("${lion.age}")int age,@Value("${lion.email}") String email){
return new Lion(name,age,email);
}
}
2、通过 @Value + @ConfigurationProperties 的方法
类信息:
@ConfigurationProperties(prefix = "lion")
public class Lion {
private final String name; // 常量属性
private static int age; // 静态属性
private String email; // 普通属性
// 构造器 初始化 常量
public Lion(String name){
this.name = name;
}
// setter 方法
public void setAge(int age){
Lion.age = age;
}
public void setEmail(String email){
this.email = email;
}
配置信息:
@Configuration
public class MyConfig {
@Bean
public Lion lion(@Value("${lion.name}") String name){
return new Lion(name);
}
}