配置动态刷新@RefreshScope引起的取值为null

配置动态刷新@RefreshScope引起的取值为null

 在Spring Cloud Config 动态刷新demo编写中,分为三个步骤:

 1)git端配置更改,代码提交

 2)手动刷新配置: POST请求: http://localhost:3355/actuator/refresh

 

 3)客户端访问配置:http://localhost:3355/testConfig

 控制类代码如下:

复制代码
 1 @RestController
 2 @RefreshScope
 3 public class ConfigClientTestController {
 4     @Value("${config.info}")
 5     private String configInfo;
 6     
 7     /**
 8      * 读取配置文件内容
 9      *
10      * @return
11      */
12     @GetMapping("testConfig")
13     private String configInfo() {
14         return configInfo;
15     }
16 }
复制代码

  这个时候发现问题,客户端根本读取不到配置。

  分析:

   1)@RefreshScope 注解是 Spring Cloud 中用于标记需要在配置发生变化时进行刷新的 bean 的注解。当一个 bean 被 @RefreshScope 注解标记时,Spring 在创建这个 bean 的代理对象时会注入一些额外的逻辑,以便在配置变化时刷新这个 bean 的属性值。

   2)代理对象是 Spring Framework 在运行时动态创建的对象,它包装了真实的 bean 对象,并在需要时执行一些额外的操作,比如在配置变化时刷新属性值。在使用 @RefreshScope 注解时,Spring 创建了一个代理对象来管理被注解标记的 bean,并在需要时负责刷新这个 bean 的属性值。

   3)当我们在调用方法时,实际上是调用了代理对象的方法,代理对象会负责处理实际的调用逻辑,包括在配置变化时刷新属性值。因此,通过方法调用可以获取到最新的属性值,但直接访问 bean 的字段可能会得到旧值或者 null,因为直接访问的是代理对象的字段,而不是真实的 bean 对象。

   根据上面的分析,将代码再改动一下:

复制代码
 1 @RestController
 2 @RefreshScope
 3 public class ConfigClientTestController {
 4     @Value("${config.info}")
 5     private String configInfo;
 6 
 7     public String getConfig() {
 8         return configInfo;
 9     }
10 
11     /**
12      * 读取配置文件内容
13      *
14      * @return
15      */
16     @GetMapping("testConfig")
17     private String configInfo() {
18         return getConfig();
19     }
20 }
复制代码

    这样就可以正常读取值了。

    @RefreshScope 会使注入的值放到代理类中,而当前bean的属性字段是没有值的,直接读取bean的field会为null,只有通过方法(不一定是get方法)才会触发去代理类中取值

   看到网上很多文章提到在@Controller中直接@Value获取不到值,解决方法是定义另外一个配置类,再取值就可以了。

   配置类:

复制代码
 1 @Component
 2 @RefreshScope
 3 public class ConfigData {
 4     @Value("${config.info}")
 5     private String configInfo;
 6 
 7     public String getConfigInfo() {
 8         return configInfo;
 9     }
10 }
复制代码

   控制类:

复制代码
 1 @RestController
 2 @RequiredArgsConstructor(onConstructor_ = {@Autowired})
 3 public class ConfigClientController {
 4 
 5     private final ConfigData configData;
 6 
 7     /**
 8      * 读取配置文件内容
 9      *
10      * @return
11      */
12     @GetMapping("getConfigInfo")
13     private String configInfo() {
14         return configData.getConfigInfo();
15     }
16 }
复制代码

  这样也能正常读取到手动刷新后的配置值。不过,归根结底,出现读取不到最新值的原因其实跟取值方式有关,都是代理惹的祸。

取值方式  无@RefreshScope 有@RefreshScope
方式1(field取值)  有值  null
方式2(方法取值)  有值  有值

 

 

 

 

 

 

 参考链接: https://www.jianshu.com/p/a535f8250cb2 

posted @   欢乐豆123  阅读(273)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2017-03-23 linux下搭建lamp环境以及安装swoole扩展
点击右上角即可分享
微信分享提示