SpringBoot 之加载配置文件

前言

SpringBoot启动时默认加载bootstrap.propertiesbootstrap.yml(这两个优先级最高)、application.propertiesapplication.yml,如果我们配置了spring.profiles,同时会加载对应的application-{profile}.propertiesapplication-{profile}.ymlprofile为对应的环境变量,比如dev,如果没有配置,则会加载profile=default的配置文件

虽然说配置项都写在同一个配置文件没有问题,但我们仍然希望能分开写,这样比较清晰,比如eureka的配置写在eureka.properties,数据库相关的配置写在datasource.properties等等,因此就需要设置加载外部配置文件。

为了让 SpringBoot 更好的生成配置元数据文件,我们需要添加如下依赖(该依赖可以不添加,但是在 IDEA 和 STS 中不会有属性提示),该依赖只会在编译时调用,所以不会对生产造成影响。

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-configuration-processorartifactId>
    <optional>trueoptional>
dependency>

使用@PropertySource加载配置文件

在启动SpringBoot之后加载任意配置文件到Environment环境中。

使用**@PropertySource**读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值。

@PropertySource(value={"classpath:xxx.properties"})
@Configuration
public class Config {
	@Value("${cn.demo.xxx:defaultValue}")
    private String xxx;
}

使用Environment加载配置文件

在运行SpringApplication之前加载任意配置文件到Environment环境中。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

import java.io.IOException;
import java.util.Objects;
import java.util.Properties;

// 自定义环境处理,在运行SpringApplication之前加载任意配置文件到Environment环境中
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {

    //Properties对象
    private final Properties properties = new Properties();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
        //自定义配置文件
        String[] profiles = {
                "db.yml"
        };

        //循环添加
        for (String profile : profiles) {
            //从classpath路径下面查找文件
            Resource resource = new ClassPathResource(profile);
            //加载成PropertySource对象,并添加到Environment环境中
            environment.getPropertySources().addLast(loadProfiles(resource));
        }
    }

    //加载单个配置文件
    private PropertySource<?> loadProfiles(Resource resource) {
        if (!resource.exists()) {
            throw new IllegalArgumentException("资源" + resource + "不存在");
        }
        try {
            //从输入流中加载一个Properties对象
            properties.load(resource.getInputStream());
            return new PropertiesPropertySource(Objects.requireNonNull(resource.getFilename()), properties);
        } catch (IOException ex) {
            throw new IllegalStateException("加载配置文件失败" + resource, ex);
        }
    }
}

并且在META-INF/spring.factories中:

#启用我们的自定义环境处理类
org.springframework.boot.env.EnvironmentPostProcessor=com.boot.demo.MyEnvironmentPostProcessor

配置文件:db.yml

db.address: nj

使用PropertySourcePlaceholderConfigurer加载配置文件

1、@PropertySource 注解只支持*.properties文件,不支持yml文件。
2、Spring Framework有两个类加载YAML文件,YamlPropertiesFactoryBeanYamlMapFactoryBean
3、可以通过PropertySourcePlaceholderConfigurer来加载yml文件,暴露yml文件到spring environment

// 加载YML格式自定义配置文件
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
	PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
	YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
	yaml.setResources(new FileSystemResource("config.yml"));//File引入
	yaml.setResources(new ClassPathResource("test.yml"));//class引入
	configurer.setProperties(yaml.getObject());
	return configurer;
}

加载配置文件总结:

  • JVM启动时,系统属性和环境变量传递给JVM。
  • SpringBoot启动时先扫描@Controller,@Component,@Configuration,@Service等注解,找到声明让Spring容器管理实例的类。
  • 看这些类上有没有@PropertySource注解,如果有则去加载该注解指定的配置文件。
  • 把所有的配置信息都给到Environment实例管理,配置信息根据来源不同有不同的优先级,比如系统属性和环境变量的优先级高于用户自定义properties文件的优先级。
  • 再判断这些类上有没有@ConfigurationProperties注解,如果有则从Environment实例中取值通过反射赋值
  • @Value注解与@ConfigurationProperties注解类似,也从Environment实例中取值通过反射赋值

注意: @PropertySource注解只要在一个被Spring容器管理的类上,那么不管在哪个类上实质是一样的,只是我们一般会写在对应的JavaBean配置类上。

属性值注入Bean的两种方式

通过@Value引入属性值注入Bean

@Value("${test.username}")
private String username;

通过@ConfigurationProperties;(调用属性的setter方法进行注入)

/**
 *
 * @ConfigurationProperties 表示 告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
 * prefix = "myuser" 表示 将配置文件中key为user的下面所有的属性与本类属性进行一一映射注入值,如果配置文件中
 * 不存在"myuser"的key,则不会为POJO注入值,属性值仍然为默认值
 * 

* @ConfigurationProperties (prefix = "myuser") 默认从全局配置文件中获取值然后进行注入 * @Component 将本来标识为一个Spring 组件,因为只有是容器中的组件,容器才会为@ConfigurationProperties提供此注入功能 */ @Component @ConfigurationProperties(prefix = "myuser") @Getter @Setter @ToString public class UserProperties { // 以下属性可以直接获取 private String name; private Integer age; }

使用建议:

  • 两种方式都可以从配置文件 *.yml*.properties 中获取到值;
  • 如果项目中只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用 @Value 即可;
  • 如果项目中专门编写了一个 JavaBean 来和配置文件进行映射,则直接使用@ConfigurationProperties即可;

Environment详解

你可能感兴趣的:(#,SpringBoot,java,开发语言,后端)