文章目录
- 3.监听事件
在Spring中有一个类Environment,它可以被认为是当前应用程序正在运行的环境,它继承了PropertyResolver接口,因此可以作为一个属性解析器使用。先创建一个yml文件,属性如下:
person:
name: hydra
gender: male
age: 18
使用起来也非常简单,直接使用@Autowired就可以注入到要使用的类中,然后调用它的getProperty()方法就可以根据属性名称取出对应的值了
@RestController
public class EnvironmentController {
@Autowired
private Environment environment;
@GetMapping("envTest")
private void getEnv(){
((""));
((""));
Integer autoClose = environment
.getProperty("", );
(autoClose);
String defaultValue = environment
.getProperty("", , "defaultValue");
(defaultValue);
}
}
在上面的例子中可以看到,除了简单的获取外,Environment提供的方法还可以对取出的属性值进行类型转换、以及默认值的设置,调用一下上面的接口,打印结果如下:
hydra
male
18
defaultValue
除了获取属性外,还可以用来判断激活的配置文件,我们先在中激活pro文件:
spring:
profiles:
active: pro
可以通过acceptsProfiles方法来检测某一个配置文件是否被激活加载,或者通过getActiveProfiles方法拿到所有被激活的配置文件。测试接口:
@GetMapping("getActiveEnv")
private void getActiveEnv(){
(("pro"));
(("dev"));
String[] activeProfiles = ();
for (String activeProfile : activeProfiles) {
(activeProfile);
}
}
true
false
pro
在Spring中还可以使用YamlPropertiesFactoryBean来读取自定义配置的yml文件,而不用再被拘束于及其激活的其他配置文件。
在使用过程中,只需要通过setResources()方法设置自定义yml配置文件的存储路径,再通过getObject()方法获取Properties对象,后续就可以通过它获取具体的属性,下面看一个例子:
@GetMapping("fcTest")
public void ymlProFctest(){
YamlPropertiesFactoryBean yamlProFb = new YamlPropertiesFactoryBean();
(new ClassPathResource(""));
Properties properties = ();
((""));
((""));
(());
}
查看运行结果,可以读取指定的的内容:
susan
female
{=18, =female, =susan}
但是这样的使用中有一个问题,那就是只有在这个接口的请求中能够取到这个属性的值,如果再写一个接口,不使用YamlPropertiesFactoryBean读取配置文件,即使之前的方法已经读取过这个yml文件一次了,第二个接口取到的仍然还是空值。来对这个过程进行一下测试:
@Value("${:null}")
private String name;
@Value("${:null}")
private String gender;
@GetMapping("fcTest2")
public void ymlProFctest2(){
(name);
(gender);
}
先调用一次fcTest接口,再调用fcTest2接口时会打印null值:
null
null
想要解决这个问题也很简单,可以配合PropertySourcesPlaceholderConfigurer使用,它实现了BeanFactoryPostProcessor接口,也就是一个bean工厂后置处理器的实现,可以将配置文件的属性值加载到一个Properties文件中。使用方法如下:
@Configuration
public class PropertyConfig {
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer configurer
= new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yamlProFb
= new YamlPropertiesFactoryBean();
(new ClassPathResource(""));
(());
return configurer;
}
}
再次调用之前的接口,结果如下,可以正常的取到中的属性:
susan
female
除了使用YamlPropertiesFactoryBean将yml解析成Properties外,其实我们还可以使用YamlMapFactoryBean解析yml成为Map,使用方法非常类似:
@GetMapping("fcMapTest")
public void ymlMapFctest(){
YamlMapFactoryBean yamlMapFb = new YamlMapFactoryBean();
(new ClassPathResource(""));
Map<String, Object> map = ();
(map);
}
打印结果:
{person2={name=susan, gender=female, age=18}}
3.监听事件
首先,定义一个类实现ApplicationListener接口,监听的事件类型为ApplicationEnvironmentPreparedEvent,并在构造方法中传入要解析的yml文件名:
public class YmlListener implements
ApplicationListener<ApplicationEnvironmentPreparedEvent> {
private String ymlFilePath;
public YmlListener(String ymlFilePath){
= ymlFilePath;
}
//...
}
自定义的监听器中需要实现接口的onApplicationEvent()方法,当监听到ApplicationEnvironmentPreparedEvent事件时会被触发:
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
ConfigurableEnvironment environment = ();
ResourceLoader loader = new DefaultResourceLoader();
YamlPropertySourceLoader ymlLoader = new YamlPropertySourceLoader();
try {
List<PropertySource<?>> sourceList = ymlLoader
.load(ymlFilePath, (ymlFilePath));
for (PropertySource<?> propertySource : sourceList) {
().addLast(propertySource);
}
} catch (IOException e) {
();
}
}
上面的代码中,主要实现了:
- 获取当前环境Environment,当ApplicationEnvironmentPreparedEvent事件被触发时,已经完成了Environment的装载,并且能够通过event事件获取
- 通过YamlPropertySourceLoader加载、解析配置文件
- 将解析完成后的OriginTrackedMapPropertySource添加到Environment中
修改启动类,在启动类中加入这个监听器:
public static void main(String[] args) {
SpringApplication application = new SpringApplication();
(new YmlListener("classpath:/"));
(args);
}