Apollo 关于ConfigurationProperties 的动态刷新

41 篇文章 0 订阅
20 篇文章 0 订阅

在我之前的博客中我 已经介绍了Apollo配置中心 结合springboot 是如何操作的了。有需要的朋友可以查看我的上一个博文

https://blog.csdn.net/HiBoyljw/article/details/86495531

我们都知道,springboot中的配置文件中的配置属性丢到Apollo之后,我们在Apollo中修改属性 那么应用就能够自动刷新了。但是其中有一个却需要我们的手动去操作那就是ConfigurationProperties 这个在关网中是这样介绍的
 

Spring Boot提供了@ConfigurationProperties把配置注入到bean对象中。

Apollo也支持这种方式,下面的例子会把redis.cache.expireSeconds和redis.cache.commandTimeout分别注入到SampleRedisConfig的expireSeconds和commandTimeout字段中。

@ConfigurationProperties(prefix = "redis.cache")
public class SampleRedisConfig {
  private int expireSeconds;
  private int commandTimeout;

  public void setExpireSeconds(int expireSeconds) {
    this.expireSeconds = expireSeconds;
  }

  public void setCommandTimeout(int commandTimeout) {
    this.commandTimeout = commandTimeout;
  }
}

在Configuration类中按照下面的方式使用(假设应用默认的application namespace中有redis.cache.expireSeconds和redis.cache.commandTimeout的配置项):

@Configuration
@EnableApolloConfig
public class AppConfig {
  @Bean
  public SampleRedisConfig sampleRedisConfig() {
    return new SampleRedisConfig();
  }
}

需要注意的是,@ConfigurationProperties如果需要在Apollo配置变化时自动更新注入的值,需要配合使用EnvironmentChangeEvent或RefreshScope。

这就意味着如果我们使用了@ConfigurationProperties 这种属性来读取配置文件的话 我们是需要 在类上加一个@RefreshScope才行。但是有些时候我们是要去读取的配置前缀却不是自己的 比如springcloud-gateway

这个时候我们是无法通过加@RefreshScope注解的方式来实现自动刷新的。这个时候怎么办呢? 别着急,我们可以去使用Apollo中更底层的办法去实现监听和自动刷新。



import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @Author: lijiawei
 * @Date: 2019/1/23 15:55
 * @Description: 用于网关属性刷新
 */
@Slf4j
@Component
public class GatewayPropertiesRefresher implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * apollo配置监听器,默认监听的是application命名空间
     *
     * @param changeEvent
     */
    @ApolloConfigChangeListener({"application-routes"})
    public void onChange(ConfigChangeEvent changeEvent) {

        boolean gatewayPropertiesChanged = false;

        for (String changedKey : changeEvent.changedKeys()) {

            //前缀为spring.cloud.gateway的key发生了改变(gateway的配置发生了改变)
            if (changedKey.startsWith("spring.cloud.gateway.")) {
                gatewayPropertiesChanged = true;
                break;
            }
        }

        //更新gateway配置
        if (gatewayPropertiesChanged) {
            refreshGatewayProperties(changeEvent);
        }
    }

    /**
     * 更新SpringApplicationContext对象,并更新路由
     *
     * @param changeEvent
     */
    private void refreshGatewayProperties(ConfigChangeEvent changeEvent) {

        log.info("Refreshing Gateway properties!");

        //更新配置
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));

        log.info("Gateway properties refreshed!");
    }

}

 或者采用下面这种方式


@Component
@Slf4j
public class AppConfig implements ApplicationContextAware {
    ApplicationContext applicationContext;

    @Autowired
    RefreshScope refreshScope;



    @ApolloConfigChangeListener(ConfigConsts.NAMESPACE_APPLICATION)
    public void onChange(ConfigChangeEvent changeEvent) {
        boolean eurekaPropertiesChanged = false;
         for (String changedKey : changeEvent.changedKeys()) {
             if (changedKey.startsWith("redis.cache")) {
                 log.info("===============================================================");
                 log.info("changedKey:{} value:{}",changedKey,changeEvent.getChange(changedKey));
                 ConfigChange configChange = changeEvent.getChange(changedKey);
                 configChange.getOldValue();
                 eurekaPropertiesChanged = true;
                 break;
             }
         }
        refreshProperties(changeEvent);
        if (eurekaPropertiesChanged) {
            refreshProperties(changeEvent);
        }
    }
    public void refreshProperties(ConfigChangeEvent changeEvent){
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
        refreshScope.refreshAll();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

就像这样。之后我们再去更改配置就能自动刷新了

 如果想了解更多的以及原理可以直接查看下官方文档:https://github.com/ctripcorp/apollo/wiki/Java%E5%AE%A2%E6%88%B7%E7%AB%AF%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97

 以上就是这次的全部内容,希望能够帮助到你

  • 10
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值