SpringBoot读取配置文件内容

857 阅读3分钟

项目中读取配置文件中内容时最常用的方法就是使用@Value注解;对于非官方指定的配置类文件,则需要借助@PropertySource注解实现注入;而在配置类中读取一组配置属性时还可以通过@ConfigurationProperties注解指定统一的前缀内容。

1. 使用@Value注解

@Value注解使用时会优先读取默认配置文件application.properties中定义的属性。

  • 使用方式为:@value("${server.port}")
  • 使用时将注解标注在成员变量上,表示将对应属性值加载到该变量中
  • 使用@Value注解时需要注意,如果不满足以下条件时,注入属性的值为null
    1. 使用了static或final修饰了字段变量,此时在容器注入对象时不会对静态变量赋值
    2. 类上没有使用@Component或其他将类加入容器的注解,类不在容器中无法注入属性
    3. 使用new创建了类的示例而不是使用@Autowired,此时不是从容器中获取,无法注入属性
public class Config{
    @Value("${server.port}")
    private String port;
}

2. @PropertySource

@PropertySource可以用来读取自定义配置文件中定义的属性。

  • 该注解可以标注在类或者接口上,设置当前类的属性读取对应的配置文件内容
  • 使用方式:@PropertySource(value={"classpath:/other.properties"})
  • 此时在类中属性上使用注解@Value("name"),读取的就是指定配置文件中的值
  • 注意,如果默认配置文件中存在同名属性,则默认配置文件的优先级更高

@PropertySource使用小细节

  1. @PropertySource加载配置文件是将指定文件同时加入到容器中,而不会覆盖,可以同名
  2. 通过注解@PropertySource导入进来的属性源的优先级是最低的
  3. 加载配置文件时,项目源路径使用classpath,绝对路径使用file:/src/...

@PropertySourceEnvironment配合使用

  • 使用@PropertySource注解将指定配置文件加入容器中
  • 注入Environment对象,通过其env.getProperty("name.short")来或取指定属性的值
 @Configuration
 @PropertySource("classpath:test.properties")
 public class TestConfig {
    @Autowired
    private Environment env;
    
    public void test(){
        String shortName = env.getProperty("name.short");
    }
 }

3. 使用@ConfigurationProperties注解

@ConfigurationProperties注解可以为配置类的属性变量指定配置文件中对应的属性前缀。

  • 使用方式:@ConfigurationProperties(prefix = "user")
  • 此时会使用默认配置文件中以user开头的属性
  • 定义属性变量时,如果类变量与配置文件属性同名,则可以不使用@Value注解
  • 也可以与@PropertySource配合使用,加载非默认配置文件中属性
@ConfigurationProperties(prefix = "user")
public class Config{
    // user.name
    private String name;
}

4. 为什么Spring容器不能注入静态变量

静态变量和静态方法属于类,而Spring容器中管理的是对象,因此使用@Autowired注入的是容器中的对象实例,所以静态方法是不能直接使用@Autowried注入的。

在使用@Value读取配置文件属性时也是类似,配置文件内容会作为Properties对象的属性管理在容器中,使用注解加载到变量上时就是使用了容器注入的机制。

因此 @Value 注解标注在 static 或 final 变量时,并不能将属性值注入,得到的值是 null。

4.1 @Autowired不能注入static成员属性的原因

Spring 不建议开发代码中为静态变量注入属性值,类加载时会优先加载静态变量,此时 Spring 的上下文环境还没有完成加载,因此不可以为静态变量绑定值。

另一方面,在 @Autowired 注解注入扫描 Class 类原数据时,会直接忽略类的使用 static 关键字标识的成员。

4.2 set 方法注入

如果想要为static变量注入值,可以间接的操作方式,比如可以通过注解标注在 set 方法(非静态)上,使用set方法注入的方式将属性值赋值到静态变量中。

 @Component
 public class Customer {
     private static String name;
     @Value("${customer.name}")
     public void setName(String name) {
         Customer.name = name;
     }
 }

如果是定义工具类,不建议在工具类中使用注入的内容,因为工具类定义的是静态方法,使用时容器并没有加载完成,会出现问题。