序
本文次要钻研一下 springboot 的 EnvironmentPostProcessor
EnvironmentPostProcessor
org/springframework/boot/env/EnvironmentPostProcessor.java
@FunctionalInterface
public interface EnvironmentPostProcessor {
/**
* Post-process the given {@code environment}.
* @param environment the environment to post-process
* @param application the application to which the environment belongs
*/
void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application);
}
springboot 提供了 EnvironmentPostProcessor 接口,该接口有 postProcessEnvironment 办法,其中 envrionment 参数类型为 ConfigurableEnvironment,即利用能够通过实现这个接口进行 env 环境变量的操作
EnvironmentPostProcessorApplicationListener
org/springframework/boot/env/EnvironmentPostProcessorApplicationListener.java
/**
* {@link SmartApplicationListener} used to trigger {@link EnvironmentPostProcessor
* EnvironmentPostProcessors} registered in the {@code spring.factories} file.
*
* @author Phillip Webb
* @since 2.4.0
*/
public class EnvironmentPostProcessorApplicationListener implements SmartApplicationListener, Ordered {
/**
* The default order for the processor.
*/
public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 10;
private final DeferredLogs deferredLogs;
private int order = DEFAULT_ORDER;
private final EnvironmentPostProcessorsFactory postProcessorsFactory;
/**
* Create a new {@link EnvironmentPostProcessorApplicationListener} with
* {@link EnvironmentPostProcessor} classes loaded via {@code spring.factories}.
*/
public EnvironmentPostProcessorApplicationListener() {
this(EnvironmentPostProcessorsFactory
.fromSpringFactories(EnvironmentPostProcessorApplicationListener.class.getClassLoader()));
}
/**
* Create a new {@link EnvironmentPostProcessorApplicationListener} with post
* processors created by the given factory.
* @param postProcessorsFactory the post processors factory
*/
public EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory) {this(postProcessorsFactory, new DeferredLogs());
}
EnvironmentPostProcessorApplicationListener(EnvironmentPostProcessorsFactory postProcessorsFactory,
DeferredLogs deferredLogs) {
this.postProcessorsFactory = postProcessorsFactory;
this.deferredLogs = deferredLogs;
}
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
|| ApplicationPreparedEvent.class.isAssignableFrom(eventType)
|| ApplicationFailedEvent.class.isAssignableFrom(eventType);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationEnvironmentPreparedEvent) {onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
}
if (event instanceof ApplicationPreparedEvent) {onApplicationPreparedEvent((ApplicationPreparedEvent) event);
}
if (event instanceof ApplicationFailedEvent) {onApplicationFailedEvent((ApplicationFailedEvent) event);
}
}
private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {ConfigurableEnvironment environment = event.getEnvironment();
SpringApplication application = event.getSpringApplication();
for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(event.getBootstrapContext())) {postProcessor.postProcessEnvironment(environment, application);
}
}
private void onApplicationPreparedEvent(ApplicationPreparedEvent event) {finish();
}
private void onApplicationFailedEvent(ApplicationFailedEvent event) {finish();
}
private void finish() {this.deferredLogs.switchOverAll();
}
List<EnvironmentPostProcessor> getEnvironmentPostProcessors(ConfigurableBootstrapContext bootstrapContext) {return this.postProcessorsFactory.getEnvironmentPostProcessors(this.deferredLogs, bootstrapContext);
}
@Override
public int getOrder() {return this.order;}
public void setOrder(int order) {this.order = order;}
}
EnvironmentPostProcessorApplicationListener 用于在接管到 ApplicationEnvironmentPreparedEvent 事件时触发执行 EnvironmentPostProcessor 的 postProcessEnvironment 办法
# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.env.EnvironmentPostProcessorApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
示例
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).get(0);
}
catch (IOException ex) {throw new IllegalStateException("Failed to load yaml configuration from" + path, ex);
}
}
}
EnvironmentPostProcessorExample 实现了 postProcessEnvironment 办法,它额定加载 com/example/myapp/config.yml 外头的配置最为最初的 propertySource
小结
springboot 的 EnvironmentPostProcessor 提供了一个 environment 的扩大接口,不便利用去做 environment 的扩大,比方扩大 propertySource 等