官方文档:
SpringApplication的ApplicationListeners和ApplicationContextInitializers可被用于将自定义应用于上下文或环境。 Spring Boot为了在内部使用,从META-INF/spring.factories加载了许多此类自定义项。 有许多种注册其他自定义的方式:
- 编程方式添加,通过在程序运行之前调用SpringApplication上的addListeners和addInitializers方法。
- 声明方式添加,通过设置context.initializer.classes或context.listener.classes声明。
- 打包成jar方式添加(所有应用),通过添加META-INF/spring.factories并打包成jar。
SpringApplication将一些特殊的ApplicationEvent发送给监听器(也包括在创建上下文之前的一些事件),然后为ApplicationContext发布的事件注册监听器。
在使用EnvironmentPostProcessor刷新应用程序上下文之前,还可以自定义环境。 每个实现都应该在META-INF/spring.factories中注册:
org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
该实现可以加载任意文件并将它们添加到环境中。 例如,此示例从类路径加载YAML配置文件:
public class EnvironmentPostProcessorExample implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource path = new ClassPathResource("com/example/myapp/config.yml");
PropertySource<?> propertySource = loadYaml(path);
environment.getPropertySources().addLast(propertySource);
}
private PropertySource<?> loadYaml(Resource path) {
if (!path.exists()) {
throw new IllegalArgumentException("Resource " + path + " does not exist");
}
try {
return this.loader.load("custom-resource", path, null);
} catch (IOException ex) {
throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
}
}
}
注:
- Environment已经准备好了Spring Boot默认加载的所有常用属性源。 因此,可以从环境中获取文件的位置。 此示例在属性源列表末尾添加custom-resource属性源。 可以自定义属性源的次序,如头部、某个属性源前/后、末尾等。
- 虽然在@SpringBootApplication上使用@PropertySource似乎方便又容易在环境中加载自定义资源,但Spring官方不推荐使用它,因为Spring Boot会在刷新ApplicationContext之前准备环境。 通过@PropertySource定义的任何key都加载的太晚以致于无法对自动配置产生任何影响。
自定义添加属性源示例:
通过spring.factories文件注册,这种方式可以打包成jar文件作为公共组件来使用。
1. 自定义配置文件config.yml
放在classpath目录下,用于在ApplicationContext刷新前添加
yaml:
server:
port: 8081
2. 编译时添加config.yml至classpath
pom.xml使用<resource>标签:
<build>
<resources>
<resource>
<filtering>false</filtering>
<directory>src/main/java</directory>
<includes>
<include>**/*.yml</include>
</includes>
</resource>
</resources>
</build>
3. 自定义EnvironmentPostProcessor
添加classpath下的confi.yml为属性源:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.IOException;
public class YamlEnvironmentPostProcessor implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Resource path = new ClassPathResource("com/momo/springbootenvironment/config/config.yml");
PropertySource<?> propertySource = loadYaml(path);
// 属性源末尾添加
environment.getPropertySources().addLast(propertySource);
}
private PropertySource<?> loadYaml(Resource path) {
if (!path.exists()) {
throw new IllegalArgumentException("Resource " + path + " does not exist");
}
try {
return this.loader.load("customConfig:[classpath:/com/momo/springbootenvironment/config/config.yml]", path, null);
} catch (IOException ex) {
throw new IllegalStateException("Failed to load yaml configuration from " + path, ex);
}
}
}
4. 注册自定义EnvironmentPostProcessor
在src/main/resources/META-INF添加spring.factories,并注册:
org.springframework.boot.env.EnvironmentPostProcessor=\
com.momo.springbootenvironment.config.YamlEnvironmentPostProcessor
5. 测试
public static void main(String[] args) {
ConfigurableApplicationContext ac = SpringApplication.run(Application.class, args);
ConfigurableEnvironment environment = ac.getEnvironment();
System.out.println("server.port:" + environment.getProperty("server.port"));
System.out.println("yaml.server.port:" + environment.getProperty("yaml.server.port"));
}
demo代码:https://github.com/mytt-10566/springboot-environment