【问题标题】:How can I execute custom logic after Spring cloud configuration refresh?Spring云配置刷新后如何执行自定义逻辑?
【发布时间】:2018-05-23 00:01:09
【问题描述】:

我已将我的应用程序设置为使用 Spring 云配置来提供配置并启用监视器,以便配置服务器将更改事件发布到我的应用程序。配置已正确更新,但我希望在配置更改时收到通知,以便我可以根据新配置执行一些自定义逻辑。

我有这个配置对象

@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "my.prefix")
public class MyConfig {
    private Map<String, MyObject> configs;
    private String someValue;

    public Map<String, MyObject> getConfigs(){...}
    public void setConfigs(){...}

    public String getSomeValue(){...}
    public void setSomeValue(){...}
}
...
public class MyObject {
   private String field1;

   public String getField1() {...}
   public void setField1() {...}
}

这在我的配置服务器 application.yml 中

my:
  prefix:
    configs:
      TEST:
        field1: "testValue"
    someValue: "test"

现在,当我在配置中更改 someValue 并且配置服务器发布刷新时,它会调用 setSomeValue() 并将值更新为新值。我可以将我的自定义逻辑添加到 setSomeValue() 并且它会正常工作。但是,在从配置中更新或添加/删除条目时,它似乎没有调用 setConfigs() 或 setField1()。

我尝试为 EnviornmentChangeEvents、RefreshEvents 或 RefreshScopeRefreshedEvents 注册一个侦听器,但这些侦听器要么在 Spring 更新值之前触发,要么根本不触发。我还尝试向 @PreDestroy 和 @PostConstruct 方法添加逻辑,但只有 PreDestroy 最终被调用,并且在配置更新之前被调用。我也尝试实现 InitializingBean 并将我的逻辑放入 afterPropertiesSet() 但它也从未被调用过。

如何在此配置更新时收到通知?

【问题讨论】:

    标签: java spring spring-boot spring-cloud spring-cloud-config


    【解决方案1】:

    使用 RefreshScopeRefreshedEvent 侦听器,您可以在配置更新时收到通知。

    以下示例适用于我:

    配置:

    @Configuration
    public class Config {
        @Bean
        @RefreshScope
        public A aBean() {
            return new A();
        }
    
        @Bean
        public RefreshScopeRefreshedListener remoteApplicationEventListener(A aBean) {
            return new RefreshScopeRefreshedListener(aBean);
        }
    
    }
    

    而听众:

    public class RefreshScopeRefreshedListener implements ApplicationListener<RefreshScopeRefreshedEvent> {
        private A aBean;
    
        public RefreshScopeRefreshedListener(A abean) {
            this.aBean = abean;
        }
    
        @Override
        public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
            System.out.println(aBean.getValue());
    
        }
    
    }
    

    它总是打印配置的新值。

    如果你已经尝试过这个监听器,你确定它已经注册好了吗? bean 是否已正确创建?

    【讨论】:

    • 这肯定会起作用,但是即使对于其他属性更改它也总是会触发该方法,我认为 RefreshScopeRefreshedEvent 中缺少的是 EnvironmentChangeEvent 可以提供的 getKeys() 方法,但是 EnvironmentChangeEvent 不保证bean @Refreshscope 已更新
    【解决方案2】:

    我所做的是获取EnvironmentChangeEvent监听器的钩子,然后从Environment本身而不是@Autowired Bean bean获取更新的属性

    @Autowired
    private Environment env;
    
    @EventListener(EnvironmentChangeEvent.class)
    public void onApplicationEvent(EnvironmentChangeEvent environmentChangeEvent) {
        log.info("Received an environment changed event for keys {}", environmentChangeEvent.getKeys());
        if(environmentChangeEvent.getKeys().contains("key.i.wanted.to.recalculate")) {
            String newValue = env.getProperty("key.i.wanted.to.recalculate");
            System.out.println("New Value: " + newValue);
        }
    }
    

    【讨论】:

      【解决方案3】:

      或者,您可以使用@ConfigurationProperties 添加@PostConstruct,以便您可以编写自定义逻辑

      @ConfigurationProperties(prefix = "dummy.just.to.trigger.actuator.refresh")
      Class AnyPropLoader {
      @PostConstruct
      private void customLogicMethod(){
      ...
      }
      }
      

      【讨论】:

        猜你喜欢
        • 2011-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-03
        • 2019-05-27
        • 2019-05-25
        • 2017-08-30
        • 2021-09-25
        相关资源
        最近更新 更多