SpringBoot启动时默认加载bootstrap.properties或bootstrap.yml(这两个优先级最高)、application.properties或application.yml,如果我们配置了spring.profiles,同时会加载对应的application-{profile}.properties或application-{profile}.yml,profile为对应的环境变量,比如dev,如果没有配置,则会加载profile=default的配置文件
虽然说配置项都写在同一个配置文件没有问题,但我们仍然希望能分开写,这样比较清晰,比如eureka的配置写在eureka.properties,数据库相关的配置写在datasource.properties等等,因此就需要设置加载外部配置文件。
为了让 SpringBoot 更好的生成配置元数据文件,我们需要添加如下依赖(该依赖可以不添加,但是在 IDEA 和 STS 中不会有属性提示),该依赖只会在编译时调用,所以不会对生产造成影响。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
在启动SpringBoot之后加载任意配置文件到Environment环境中。
使用**@PropertySource**读取外部配置文件中的k/v保存到运行的环境变量中;加载完外部的配置文件以后使用${}取出配置文件的值。
@PropertySource(value={"classpath:xxx.properties"})
@Configuration
public class Config {
@Value("${cn.demo.xxx:defaultValue}")
private String xxx;
}
在运行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
1、@PropertySource
注解只支持*.properties
文件,不支持yml
文件。
2、Spring Framework
有两个类加载YAML
文件,YamlPropertiesFactoryBean
和YamlMapFactoryBean
。
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;
}
注意: @PropertySource注解只要在一个被Spring容器管理的类上,那么不管在哪个类上实质是一样的,只是我们一般会写在对应的JavaBean配置类上。
通过@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详解