【问题标题】:Plug into the hierarchy of Spring Boot property sources插入 Spring Boot 属性源的层次结构
【发布时间】:2017-01-02 20:26:32
【问题描述】:

我知道spring属性源的默认顺序:http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html 如何添加具有特定优先级的自己的属性源?

@PropertySource 还不够,因为它添加了优先级很低的新属性

【问题讨论】:

    标签: java spring spring-boot spring-properties


    【解决方案1】:

    有很多方法可以做到这一点; I'll just quote the official documentation:

    SpringApplication 具有 ApplicationListeners 和 ApplicationContextInitializers,用于将自定义应用于上下文或环境。 Spring Boot 会从 META-INF/spring.factories 加载许多此类自定义以供内部使用。注册额外的方法不止一种:

    • 在运行之前,通过在 SpringApplication 上调用 addListenersaddInitializers 方法,以编程方式按应用程序运行。
    • 通过设置context.initializer.classescontext.listener.classes 以声明方式为每个应用程序。
    • 通过添加 META-INF/spring.factories 并打包应用程序都用作库的 jar 文件,以声明方式为所有应用程序提供。

    SpringApplication 向侦听器发送一些特殊的ApplicationEvents(甚至在创建上下文之前),然后也为 ApplicationContext 发布的事件注册侦听器。有关完整列表,请参阅“Spring Boot 功能”部分中的Section 23.4, “Application events and listeners”

    还可以在使用EnvironmentPostProcessor 刷新应用程序上下文之前自定义Environment。每个实现都应该在META-INF/spring.factories注册:

    org.springframework.boot.env.EnvironmentPostProcessor=com.example.YourEnvironmentPostProcessor
    

    我的方法总是添加一个 ApplicationEnvironmentPreparedEvent 监听器:

    public class IntegrationTestBootstrapApplicationListener implements
        ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
    
        public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 4;
        public static final String PROPERTY_SOURCE_NAME = "integrationTestProps";
    
        private int order = DEFAULT_ORDER;
    
        public void setOrder(int order) {
            this.order = order;
        }
    
        @Override
        public int getOrder() {
            return this.order;
        }
    
        @Override
        public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
            ConfigurableEnvironment environment = event.getEnvironment();
    
            if (!environment.getPropertySources().contains(PROPERTY_SOURCE_NAME)) {
                Map<String, Object> properties = ...; // generate the values
    
                // use whatever precedence you want - first, last, before, after
                environment.getPropertySources().addLast(
                  new MapPropertySource(PROPERTY_SOURCE_NAME, properties));
            }
        }
    
    }
    

    但您也可以轻松地使用初始化器:

    public class IntegrationTestBootstrapApplicationListener implements
        ApplicationContextInitializer<ConfigurableApplicationContext> {
    
        private static final String PROPERTY_SOURCE_NAME = "integrationTestProps";
    
        @Override
        public void initialize(final ConfigurableApplicationContext applicationContext) {
            ConfigurableEnvironment environment = applicationContext.getEnvironment();
            Map<String, Object> properties = ...; // generate the values
    
            // use whatever precedence you want - first, last, before, after
            environment.getPropertySources().addLast(
                new MapPropertySource(PROPERTY_SOURCE_NAME, properties));
        }
    }
    

    【讨论】:

    • 你能描述一下 make spring 来检测你的初始化器吗?这个类在哪里使用?
    • 引用的文字中已经有说明,详情见项目符号列表。
    • 添加到 META-INF/spring.factories 对我不起作用
    • 该功能不太可能不起作用,因为整个 Spring Boot 的自动配置都依赖于 spring.factories,您可能在某个地方犯了错误:)
    猜你喜欢
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 2018-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多