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中,有分布式配置中心组 ...
随机推荐
- Eureka 开发时快速剔除失效服务
Spring Cloud 版本: Dalston.SR5 服务端配置: # 关闭保护机制 eureka.server.enable-self-preservation=false #剔除失效服务间隔 ...
- [学习笔记]Javascript采用二进制浮点数和四舍五入的错误
1.样例 var a = .3 - .2 //0.09999999999999998 var b = .2 - .1 //0.1 a == b //false 出现这样的原因在于 1.Javascri ...
- Android Studio gradle配置详解
android gradle配置详解 AppExtension类及其属性 可能大部分人看到AppExtension类会感觉到非常的陌生,其实我们在app中的build.gradle中填写配置信息的时候 ...
- 用javascript判断当前是安卓平台还是ios平台
通常判断运行环境都是通过navigator.userAgent if (/android/gi.test(navigator.userAgent)){ // todo : android} if (/ ...
- C++ code:函数指针数组
函数指针作为一种数据类型,当然可以作为数组的元素类型.例如,要实现用菜单来驱动函数调用的程序框架,则用函数指针数组来实现就比较容易维护. #include<iostream> using ...
- inoremap nnoremap vnoremap
原贴:https://www.xuebuyuan.com/zh-hant/1116162.html inoremap nnoremap vnoremap i insert 在插入模式有效 n 在 普通 ...
- hdu5358 推公式+在一个区间内的尺取+枚举法
尺取+枚举,推出公式以后就是一个枚举加尺取 但是这题的尺取不是对一个值尺取,而是在一个区间内,所以固定左边界,尺取右边界即可 #include<bits/stdc++.h> #define ...
- SPLAY,LCT学习笔记(六)
这应该暂时是个终结篇了... 最后在这里讨论LCT的一个常用操作:维护虚子树信息 这也是一个常用操作 下面我们看一下如何来维护 以下内容转自https://blog.csdn.net/neither_ ...
- 绝对定位后,position:absolute;不能使用margin: 0 auto;实现居中;
声明: web小白的笔记,欢迎大神指点!联系QQ:1522025433. 我们都知道margin: 0 auto:可也实现块状元素的水平居中:但是对于绝对顶为的元素就会失效: 请看实例: <!d ...
- OpenLDAP在win2008上安装配置
业务需要,将企业员工信息统一管理,OpenLdap是目录数据库和一套访问协议组成的系统,适合使用,它有以下特点: LDAP的结构用树来表示 C/S模型,Server用户存储数据,Client为操作目录 ...