spring 配置动态刷新
Apollo
分布式 apollo 简介
Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。
本文主要介绍如何使用 apollo 与 springboot 实现动态刷新配置,如果之前不了解 apollo 可以查看如下文档
学习了解一下 apollo,再来查看本文
apollo 与 spring 实现动态刷新配置本文主要演示 2 种刷新,一种基于普通字段刷新、一种基于 bean 上使用了 @ConfigurationProperties 刷新
1、普通字段刷新(@Value)
== 不需要额外配置,直接就可以动态刷新 ==
a、pom.xml 配置
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.6.0</version>
</dependency>
b、客户端配置 AppId,Apollo Meta Server
此配置有多种方法,本示例直接在 application.yml 配置,配置内容如下
app:
id: ${
spring.application.name}
apollo:
meta: http://192.168.88.128:8080,http://192.168.88.129:8080
bootstrap:
enabled: true
eagerLoad:
enabled: true
c、项目中启动类上加上 @EnableApolloConfig 注解,形如下
@SpringBootApplication
@EnableApolloConfig(value = {
"application","user.properties","product.properties","order.properties"})
public class ApolloApplication {
public static void main(String[] args) {
SpringApplication.run(ApolloApplication.class, args);
}
}
@EnableApolloConfig 不一定要加在启动类上,加在被 spring 管理的类上即可
d、在需刷新的字段上配置 @Value 注解,形如
@Value("${hello}")
private String hello;
通过以上三步就可以实现普通字段的动态刷新
2、bean 使用 @ConfigurationProperties 动态刷新
bean 使用 @ConfigurationProperties 注解目前还不支持自动刷新,得编写一定的代码实现刷新。目前官方提供 2 种刷新方案
- 基于 RefreshScope 实现刷新
- 基于 EnvironmentChangeEvent 实现刷新
- 本文再提供一种,当 bean 上如果使用了 @ConditionalOnProperty 如何实现刷新
a、基于 RefreshScope 实现刷新
1、pom.xml 要额外引入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.0.3.RELEASE</version>
</dependency>
2、bean 上使用 @RefreshScope 注解
@Component
@ConfigurationProperties(prefix = "product")
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@RefreshScope
public class Product {
private Long id;
private String productName;
private BigDecimal price;
}
3、利用 RefreshScope 搭配 @ApolloConfigChangeListener 监听实现 bean 的动态刷新,其代码实现如下
@ApolloConfigChangeListener(value="product.properties")
private void refresh(ConfigChangeEvent changeEvent){
refreshScope.refresh("product");
PrintChangeKeyUtils.printChange(changeEvent);
}
@ApolloConfigChangeListener 注解
| 参数 | 作用 | 类型 | 默认值 | 示例 |
|---|---|---|---|---|
| value / configNames | 指定要监听的 Apollo 命名空间(namespace)列表 | String[] | 空数组(监听 application) | @ApolloConfigChangeListener({“app1”, “app2”}) |
| interestedKeyPrefixes | 仅监听以指定前缀开头的配置项变更(过滤无关配置) | String[] | 空数组(监听所有) | @ApolloConfigChangeListener(interestedKeyPrefixes = “spring.redis”) |
| interestedKeys | 明确指定要监听的配置项 Key(完全匹配) | String[] | 空数组(监听所有) | @ApolloConfigChangeListener(interestedKeys = {“timeout”, “max.retries”}) |
| ignoreNamespaceNotFound | 是否忽略未找到命名空间的错误(避免启动失败) | boolean | false(严格模式) | @ApolloConfigChangeListener(value = “optional-ns”, ignoreNamespaceNotFound = true) |
b、基于 EnvironmentChangeEvent 实现刷新
利用 spring 的事件驱动配合 @ApolloConfigChangeListener 监听实现 bean 的动态刷新,其代码如下
@Component
@Slf4j
public class UserPropertiesRefresh implements ApplicationContextAware {
private ApplicationContext applicationContext;
@ApolloConfigChangeListener(value="user.properties",interestedKeyPrefixes = {
"user."})
private void refresh(ConfigChangeEvent changeEvent){
applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
PrintChangeKeyUtils.printChange(changeEvent);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
c、当 bean 上有 @ConditionalOnProperty 如何实现刷新
当 bean 上有 @ConditionalOnProperty 注解时,上述的两种方案可以说失效了,因为 @ConditionalOnProperty 是一个条件注解,当不满足条件注解时,bean 是没法注册到 spring 容器中的。如果我们要实现此种情况的下的动态刷新,我们就得自己手动注册或者销毁 bean 了。其实现流程如下
1、当满足条件注解时,则手动创建 bean,然后配合 @ApolloConfigChangeListener 监听该 bean 的属性变化。当该 bean 属性有变化时,手动把属性注入 bean。同时刷新依赖该 bean 的其他 bean
2、当不满足条件注解时,则手动从 spring 容器中移除 bean,同时刷新依赖该 bean 的其他 bean
其刷新核心代码如下
public class OrderPropertiesRefresh implements ApplicationContextAware {
private ApplicationContext applicationContext;
@ApolloConfig(value = "order.properties")
private Config config;
@ApolloConfigChangeListener

最低0.47元/天 解锁文章
4753

被折叠的 条评论
为什么被折叠?



