关于如何让 static 修饰的字段动态获到取 nacos 的值
前言
在平时的开发中,我们一般使用 nacos 来作为项目的注册中心和配置中心,其中配置中心的动态化配置又是我们经常要用到的设置。配置一些经常发生变化的值特别好用,不需要重启项目,不需要修改代码,只需要在 nacos 的配置文件修改完成,保存一下就可以完成动态配置。这次我想专门记录一下对于 static 修饰的值如何获取到值与动态的刷新该值。
正常使用案例
首先我们先看一下最为经典的用法,也就是非 static 字段的使用,我首先在 nacos 中了如下这么一段配置。
在代码中我是通过下面代码获取到 nacos 配置的值,我个人习惯用 @ConfigurationProperties 指定前缀并搭配 @Configuration 来使用,通过 set 来赋值,同时加一个注解 RefreshScope 来开启动态刷新。
1 |
|
简单写一个方法,打印出来
1 |
|
通过日志我们可以看到获取成功且没有问题,修改值也可以及时更新,这里就不过多赘述,我们进入 static 部分
搭配 static 使用案例
现在我们把所有的字段变为 static,重启代码试一下是否还可以获取到值
1 |
|
很明显,获取到的对象是空的。可以判断出我们修改成了 static,变为静态字段后,初始化是在类加载的时候,早于 nacos 的创建实例阶段,所以我们的字段跟着类加载的时候已经有了默认值,后面 nacos 的值自然赋值不上,除非我们显示的修改,那么我们要如何获取到 nacos 的值呢?
首先先来看一下实体类,与之前唯一不同的地方就是我们只需要手动去创建字段的 get 和 set 方法,注意这里使用 idea 的快捷生成会在方法顺带加上 static 关键字,我们需要手动的把 get 和 set 方法上的 static 删掉。
1 |
|
同时在我们需要使用这个对象的类里,引入 NacosVo 这个对象并初始化。
1 | private static NacosVo nacosVo; |
启动程序,我们可以看到成功获取到了 nacos 中的值,我们尝试改变一下数据发现仍然可以获取到最新的记录,将 nacos 的属性信息赋值给静态字段并实现动态刷新就完成了
原理剖析
我们来看这样一组实例
在程序刚启动后,我分别通过 2 种方式获取 nacos 的配置,打印出的结果是一样的,下面我改变 nacos 的值并重新获取,可以看到,通过 get 方法获取的值是最新的,但是类名获取的仍然是第一次 nacos 的值。
为什么会发生这种情况呢?首先我们需要知道 @RefreshScope
这个注解的作用,这个注解是标记一个 Bean 或者类,在配置发生变化的时候,Spring 会重新创建该容器。而 nacos 也有一个监听类,叫做 NacosConfigProperties
,是用来监听 nacos 配置发生变化的,这两个组件的作用下,该 bean 会重新创建。所以后续通过 get 方法获取到的都是从最新的该 bean 中拿到的数据,而类名获取到的则是我们启动框架的时候,初始化进去的当前 nacos 值,同时因为是 static 修饰的,跟着类一起加载,如果后续我们没有进行显示的更改,那么是不会发生变化的。
最后总结一下,NacosConfigProperties
是负责监听 Nacos 配置变化的组件,而 RefreshScope
是负责动态刷新 Bean 的组件。它们一起工作,使得应用程序能够在配置发生变化时自动更新,并实现动态刷新 Bean 的属性值。