在apollo官方描述配置变化时自动更新时,提到有两种方法:
EnvironmentChangeEvent 或 RefreshScope
1.这里描述一下用EnvironmentChangeEvent中遇到的坑,
apollo推荐的demo是在监听中用下面代码更新
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
如果更改数据源配置的话,druid会抛出个异常,因为在druid的bean设置值的时候会判断druid是否初始化
以下为DruidAbstractDataSource.java中setUrl(),如果初始化过了就会抛出一个异常。这就需要我们人工手动关闭Druid中的数据库连接,且设置为未初始化,个人技术不到位,试了几次都有其他异常。
public void setUrl(String jdbcUrl) {
if (StringUtils.equals(this.jdbcUrl, jdbcUrl)) {
return;
}
//如果初始化就会抛出异常
if (inited) {
throw new UnsupportedOperationException();
}
if (jdbcUrl != null) {
jdbcUrl = jdbcUrl.trim();
}
this.jdbcUrl = jdbcUrl;
// if (jdbcUrl.startsWith(ConfigFilter.URL_PREFIX)) {
// this.filters.add(new ConfigFilter());
// }
}
2.于是我们采用了第二种方式RefreshScope
在Druid配置类中添加注解 @EnableApolloConfig @RefreshScope
@Configuration
@EnableApolloConfig
public class DruidConfig {
@RefreshScope
@ConfigurationProperties(prefix="spring.datasource")
@Bean
public DataSource druid() {
return new DruidDataSource();
}
}
在apollo监听类中
@Component
public class ApolloConfig {
@Autowired
private org.springframework.cloud.context.scope.refresh.RefreshScope refreshScope;
@ApolloConfigChangeListener()
private void configChange(ConfigChangeEvent changeEvent){
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
logger.info("配置发生变化 {}", change.toString());
refresh(key);
}
}
private void refresh(String key) {
if (key.contains("spring.datasource")) {
//这里是根据你声明的Bean名称来的
refreshScope.refresh("druid");
}
}
}
直接运行,在apollo配置中更改数据源,也能实时刷新