关于springboot:聊聊springboot的EnvironmentPostProcessor

46次阅读

共计 5304 个字符,预计需要花费 14 分钟才能阅读完成。

本文次要钻研一下 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 等

正文完
 0