美文网首页
SpringCloud之如何配置文件自动刷新配置

SpringCloud之如何配置文件自动刷新配置

作者: Wannay | 来源:发表于2022-01-17 23:39 被阅读0次

    1. 刷新环境Environment的理论分析

    在之前我们已经提过bootstrap配置文件的生效,是直接在BootstrapApplicationListener中建立一个隔离的bootstrap容器,从而得到刷新完成的容器的环境对象,并和app容器的环境对象去进行合并。

    我们知道bootstrap配置文件自然是为了实现SpringCloud中很重要的一环,那就是分布式配置中心,我们下面以Nacos为例。

    首先我们知道只要启动app容器,并且里面包含了BootstrapApplicationListener这个监听器,那么就会启动bootstrap容器,并将里面的ApplicationContext的初始化器转移到app容器当中去,当ApplicationContext创建好时,就会自动回调ApplicationContext的初始化器。

    而其中一个组件PropertySourceBootstrapConfiguration,它会自动注入容器中所有的类型的PropertySourceLocator组件。

    image.png

    在它对ApplicationContext去进行准备工作的回调方法如下

    image.png

    我们可以看到,它做的事情就是遍历所有的Locator,去执行它的locateCollection方法。

    image.png

    我们可以看到,locateCollection方法其实就是回调locate方法,去加载属性源(PropertySource,也就是对配置文件的抽象)。

    Nacos中就实现了这样一个组件NacosPropertySourceLocator

    image.png

    我们可以发现,这就是去ConfigServer当中去加载配置文件的逻辑。

    从以上的分析当中,我们可以知道,构建一个app容器,就能得到完整的环境信息。实际上是依赖BootstrapApplicationListener去构建的隔离容器,最终实现的ConfigServer中配置文件的加载。

    其实在Spring中就是这样去做的,构建一个mini版本的app容器,因为容器就会去回调Locator,因此就能得到完整的环境信息。再将该容器的环境信息,和真正的app容器去进行合并,就得到了更新之后的环境信息。

    2. 在Spring当中的落地实现

    自动刷新的入口在RefreshEventListener这个组件

    image.png

    我们可以看到,它监听了RefreshEvent事件,当这个事件被发布时,就会回调ContextRefresherrefresh方法去完成配置文件的刷新工作。

    image.png

    从上面的代码中,我们可以将其分为三步:

    • 1.updateEnvironment,更新环境对象,它是一个模板方法,交给子类去进行实现。
    • 2.发布EnvironmentChangeEvent事件。
    • 3.scope.refreshAll

    2.1 更新环境信息

    我们先来看第一步(找到子类LegacyContextRefresherupdateEnvironment方法)

    image.png

    我们可以看到,其实这就是构建一个mini的app容器,并设置监听器为BootstrapApplicationListener,在刷新完容器,拿到它执行完成的环境对象,去更新原来的app环境当中的环境信息。

    2.2 发布环境改变事件并进行rebind

    接着来看第二步,发布EnvironmentChangeEvent事件,其中一个组件ConfigurationPropertiesRebinder,就监听了这个事件。

    image.png

    我们可以看到,当环境发生改变的事件发布之后,它就会遍历所有的标有@ConfigurationProperties注解的Bean去进行rebind,下面我们来看rebind做了什么?

    image.png

    我们可以看到,首先是摧毁Bean,然后就是对Bean去进行重新初始化(重新初始化的过程中,就会有处理@ConfigurationProperties注解的Bean去进行值的设置)

    我们来看ConfigurationPropertiesBeans这个组件是如何收集@ConfigurationProperties的组件的?

    image.png

    我们可以看到,它是一个BeanPostProcessor,可以在Bean初始化前后去进行干预,它首先把RefreshScopeBean给排除掉,再去扫描@ConfigruationProperties注解,也就是说,它维护的是非RefreshScope,并且标注了@ConfigurationProperties注解的组件。

    2.3 刷新RefreshScope作用域内的Bean

    image.png image.png

    我们可以看到,它先将自己的作用域的Bean去进行destory(将自己这个作用域内的Bean的缓存直接清空,并完成destroy回调),然后发布RefreshScopeRefreshedEvent事件。

    RefreshScope这个作用域被刷新时,代表下次获取RefreshScope内的Bean时,就得重新调用createBean方法去创建一个Bean,重新创建,自然是会拿到新的配置信息,能实现刷新效果,没毛病。

    如何让自己成为一个RefreshScopeBean呢?给一个Bean上标上@RefreshScope注解即可。

    2.4 用到的相关组件从何而来?

    cloud-context包的spring.factories当中配置了下面这个配置类,会给容器中导入ConfigurationPropertiesBeansConfigurationPropertiesRebinder组件,去支持@ConfigurationProperties注解的Beanrebind

    image.png

    2.5 Nacos如何整合Spring去进行发布事件?

    Nacos通过spring.factories给容器中导入了NacosConfigAutoConfiguration这个组件,这个组件内部给容器中导入了一堆组件。

    image.png

    其中我们需要关注的组件是NacosContextRefresher

    image.png

    这个组件它也是一个监听器,负责监听容器已经启动完成的事件,当容器启动完成的事件发布之后,它就会将已经注册的全部属性源的dataId配合group,注册一个监听器到NacosConfigService当中去,而监听器内部做的事就是发布RefreshEvent事件。

    image.png

    NacosConfigServer中的配置信息发生了改变,就会推送消息给NacosClient,而此时NacosClient就会回调相应的监听器,回调监听器时,自然就肯定会发布RefreshEvent事件。

    RefreshEvent事件到来时,就会触发我们上面提到的刷新工作,将@ConfigurationProperties注解的Bean@RefreshScope的Bean`去完成刷新,完成刷新工作之后,下次我们再访问相应的对象时,就会拿到新的对象,获取到新的属性值,从而实现配置文件的自动。

    2.6 总结

    image.png

    相关文章

      网友评论

          本文标题:SpringCloud之如何配置文件自动刷新配置

          本文链接:https://www.haomeiwen.com/subject/lpihhrtx.html