EnvironmentPostProcessor

简介(What)

EnvironmentPostProcessor是Spring Boot提供的一个后置处理器,用于处理Spring应用的ConfigurableEnvironment对象,如添加默认值。

定义(Definition)

EnvironmentPostProcessor是一个函数接口,定义如下:

package org.springframework.boot.env;

@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);

}

用法(Usage)

本文以修改Spring Boot应用的默认服务端口为例,示例如何使用EnvironmentPostProcessor对Spring Boot的环境变量进行修改。

在默认情况下,Spring Boot应用的默认服务端口为8080, 也可以通过server.port进行修改,但是这种修改仅对当前项目起作用, 如何对某个公司或组织下的所有项目进行默认的服务商品进行修改呢?

首先,自定义一个实现了EnvironmentPostProcessor类,如修改默认端口,通常情况下,

public class ServerEnvironmentPostProcessor implements EnvironmentPostProcessor {

    public static final String SERVER_PORT_PROPERTY_NAME = "server.port";

    @Override
    public void postProcessEnvironment(final ConfigurableEnvironment environment, final SpringApplication application) {
        environment.getPropertySources()
            .addLast(new MapPropertySource("defaultServerProperties",
                Collections.singletonMap(SERVER_PORT_PROPERTY_NAME, 80)));
    }

}

上述代码相当于在application配置文件中声明了如下配置:

server.port=80

然后,在classpath:/META-INF/spring.factories文件中添加如下配置:

# EnvironmentPostProcessor
org.springframework.boot.env.EnvironmentPostProcessor=\
org.ifinalframework.boot.env.ServerEnvironmentPostProcessor

启动Spring应用,服务将运行在80端口。

上述实现,仅在未显示指定server.port的情况下有效,这是因为此处使用的是addLast()进行的配置,如果想忽略显示指定的配置,可使用addFirst()方式注入。

原理(How)

从Spring Boot 2.4.0开始,引入了EnvironmentPostProcessorApplicationListener应用监听器。

该接口实现了SmartApplicationListener,并重写了supportsEventType(Class)方法,支持以下类型的ApplicationEvent:

@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
    return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType)
            || ApplicationPreparedEvent.class.isAssignableFrom(eventType)
            || ApplicationFailedEvent.class.isAssignableFrom(eventType);
}

因此,当SpringApplication准备好Envirmonent并发布ApplicationEnvironmentPreparedEvent 事件,会回调其onApplicationEvent(ApplicationEvent)方法,从而触发onApplicationEnvironmentPreparedEvent()方法:

@Override
public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof ApplicationEnvironmentPreparedEvent) {
        onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
    }
    if (event instanceof ApplicationPreparedEvent) {
        onApplicationPreparedEvent();
    }
    if (event instanceof ApplicationFailedEvent) {
        onApplicationFailedEvent();
    }
}

onApplicationEnvironmentPreparedEvent()方法中,通过调用SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor. class, classLoader)加载声明在/META-INF/spring.factories文件中的EnvironmentPostProcessor实例。

EnvironmentPostProcessor

小结(End)

本文以服务端口server.port为例,简述了Spring环境后置处理器的基本使用及其实现原理,开发者可以使用该扩展对Spring默认环境进行处理或自定义, 更大限度地提高程序开发效率。