spring cloud:config-server中@RefreshScope的"陷阱"
spring cloud的config-serfver主要用于提供分布式的配置管理,其中有一个重要的注解:@RefreshScope,如果代码中需要动态刷新配置,在需要的类上加上该注解就行。但某些复杂的注入场景下,这个注解使用不当,配置可能仍然不动态刷新,比如下面的场景:
1. 先定义一个配置类(假设这里面定义了一个apiUrl,表示调用的api地址)
@Component
@ConfigurationProperties(prefix = "demo.app")
@Data
@RefreshScope
public class DemoServiceAppConfig {
/**
* api调用地址
*/
private String apiUrl = "";
}
对应的yml配置类似:
demo:
app:
apiUrl: "http://11111.com/xxxxx"
2. 然后定义一个工具类,用于封装调用外部api
@Data
@RefreshScope
public class TestUtil { private String apiUrl; public void callApi() {
System.out.println("apiUrl:" + apiUrl);
}
}
3. 为了避免1中的配置类,与2中的工具类强耦合,搞一个bean注入容器把他们关联起来
@Component
@RefreshScope
public class BeanContainer { @Autowired
DemoServiceAppConfig appConfig; @Bean
private TestUtil testUtil() {
TestUtil testUtil = new TestUtil();
testUtil.setApiUrl(appConfig.getApiUrl());
return testUtil;
} }
4 最后来一个Controller测试下
@RestController
@RefreshScope
@Api(consumes = "application/json",
produces = "application/json",
protocols = "http",
basePath = "/")
public class PingController extends AbstractController { @Autowired
DemoServiceAppConfig appConfig; @Autowired
TestUtil testUtil; @RequestMapping(value = "/test", method = {RequestMethod.GET, RequestMethod.POST})
public String test() {
return "config.apiUrl=>" + appConfig.getApiUrl() + "<br/>testUtil.apiUrl=>" + testUtil.getApiUrl();
} }
注:上面所有这些类,都加了@RefreshScope标签。
跑起来,效果如下:

然后把yml文件改下,然后push到git上,再curl -X POST http://localhost:7031/refresh 刷一把配置

可以看到,通过testUtil调用的方法中,取到的apiUrl值仍然是旧的,并没有动态刷新!
正确姿势如下:

最后一个问题,@RefreshScope作用的类,不能是final类,否则启动时会报错,类似下面这堆:
Caused by: java.lang.IllegalArgumentException: Cannot subclass final class TestUtil
at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:565) ~[spring-core-4.3.9.RELEASE.jar:4.3.9.RELEASE]
从出错信息上看,底层应该是使用cglib进行增强,需要在TestUtil下派生子类。
然后,由cglib又引出了更一个坑,如果在一些web核心组件相关的config上误加了@RefreshScope, 比如下面这样:
@Bean
@RefreshScope
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
这里面有一个org.springframework.web.cors.CorsConfiguration配置类,加了@RefreshScope后,org.springframework.web.filter.GenericFilterBean#init 这个核心bean的init就会报错,要么应用启不起来,要么请求时报内部错误。
最后,还有一个要注意的坑,比如:
abc: "xxx"
如果yml文件中有一个这样的属性,改成:
abc: ""
即变成空后,就算再curl -X POST http://.../refresh 接口,代码中拿到的值,仍然是xxx,建议如果要让一个属性值失效,可以约定一个特定值,比如
abc:"NULL"
然后代码中用“NULL”来判断.
spring cloud:config-server中@RefreshScope的"陷阱"的更多相关文章
- 为Spring Cloud Config Server配置远程git仓库
简介 虽然在开发过程,在本地创建git仓库操作起来非常方便,但是在实际项目应用中,多个项目组需要通过一个中心服务器来共享配置,所以Spring Cloud配置中心支持远程git仓库,以使分散的项目组更 ...
- ubuntu14.04 spring cloud config server + gradle搭建
Server端:在eclipse上,创建Java Project项目.自带的src包删掉手动建文件夹.基础的目录文件都创建上 |--ZSpringCloud|--build.gradle|----sr ...
- Spring Cloud Config Server 节点迁移引起的问题,请格外注意这一点!
前言: 虽然强烈推荐选择使用国内开源的配置中心,如携程开源的 Apollo 配置中心.阿里开源的 Nacos 注册&配置中心. 但实际架构选型时,根据实际项目规模.业务复杂性等因素,有的项目还 ...
- spring cloud config配置中心源码分析之注解@EnableConfigServer
spring cloud config的主函数是ConfigServerApplication,其定义如下: @Configuration @EnableAutoConfiguration @Enab ...
- Spring Cloud Config中文文档
https://springcloud.cc/spring-cloud-config.html 目录 快速开始 客户端使用 Spring Cloud Config服务器 环境库 健康指标 安全 加密和 ...
- spring cloud config将配置存储在数据库中
Spring Cloud Config Server最常见是将配置文件放在本地或者远程Git仓库,放在本地是将将所有的配置文件统一写在Config Server工程目录下,如果需要修改配置,需要重启c ...
- Spring Cloud Config 配置中心实践过程中,你需要了解这些细节!
本文导读: Spring Cloud Config 基本概念 Spring Cloud Config 客户端加载流程 Spring Cloud Config 基于消息总线配置 Spring Cloud ...
- Spring Cloud config之三:config-server因为server端和client端的健康检查导致服务超时阻塞问题
springcloud线上一个问题,当config-server连不上git时,微服务集群慢慢的都挂掉. 在入口层增加了日志跟踪问题: org.springframework.cloud.config ...
- springboot+cloud 学习(五)统一配置中心 spring cloud config + cloud bus + WebHooks +RibbitMQ
前言 微服务要实现集中管理微服务配置.不同环境不同配置.运行期间也可动态调整.配置修改后可以自动更新的需求,Spring Cloud Config同时满足了以上要求.Spring Cloud Conf ...
- SpringCloud(6)分布式配置中心Spring Cloud Config
1.Spring Cloud Config 简介 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件.在Spring Cloud中,有分布式配置中心组 ...
随机推荐
- zabbix系列(十)zabbix添加对zookeeper集群的监控
1.应用场景描述 在目前公司的业务中,有部分ESB架构用ZooKeeper作为协同服务的场景,做好ZooKeeper的监控很重要. 2.ZooKeeper监控要点 系统监控 内存使用量 ZooK ...
- CentOS 6.5下的lamp环境rsyslog+MySQL+loganalyzer实现日志集中分析管理
前言 rsyslog系统日志,在CentOS5上叫syslog,而在CentOS6上叫rsyslog,是增强版的syslog,CentOS5上的配置文件在/etc/syslog.conf下,而Cent ...
- 服务发现之consul的介绍、部署和使用
什么是服务发现 微服务的框架体系中,服务发现是不能不提的一个模块.我相信了解或者熟悉微服务的童鞋应该都知道它的重要性.这里我只是简单的提一下,毕竟这不是我们的重点.我们看下面的一幅图片: 图中 ...
- rsync使用详解
1.什么是Rsync Rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件.Rsync使用所谓的“Rsync算法”来使本地和远 程两个 ...
- css之absolute
一.absolute和float有相同的特性,包裹性和破坏性 1.absolute和float的相似(看下面的demo,如果图片在左上角,那么用float和absolute都一样) <!doct ...
- python之比较is与==(转载)
在 Python 中会用到对象之间比较,可以用 ==,也可以用 is .但是它们的区别是什么呢? is 比较的是两个实例对象是不是完全相同,它们是不是同一个对象,占用的内存地址是否相同.莱布尼茨说过: ...
- MACE(3)-----工程化
作者:十岁的小男孩 QQ:929994365 能下者,上. 前言 本文是MACE的第三步即MACE环境编译出来的库在Android工程中的使用.在第一篇博文中通过mace官方提供的安卓工程进行调试,本 ...
- poj3667 区间合并,找最左边的空余块
题很简单:给两个操作1:查找最左边的a个空余块并填满 2:把从第a个开始的连续b个块置空 线段树维护左连续,右连续,最大连续,lazy-tag即可,query函数值得学习 #include<io ...
- webpack - require 概要
webpack 是一个预编译模块打包工具,它只会对使用到的模块进行打包. 一个模块是否被使用?可以根据该模块是否被 require 来判断.如果require时指定的是具体的模块名称与正确的路径,那么 ...
- pyinstaller将py文件转成exe格式
首先要注意一下:打包python文件成exe格式这个过程只能在windows环境下运行 1. 直接在命令行用pip安装 pyinstaller pip install pyinstaller 2. 下 ...