SpringCloud Alibaba Nacos 配置动态更新源码学习总结(二)

书接上回SpringCloud Alibaba Nacos 配置动态更新源码学习总结
主要看了Spring Cloud Alibab Nacos的动态配置原理,依赖于部分的spring cloud的组件,比如org.springframework.cloud.bootstrap.BootstrapConfiguration,在启动之前进行干预项目启动,那么在之前springboot项目怎么实现的呢,主要看
nacos-group下面的nacos-config-spring-boot-starer

源码位置:https://github.com/nacos-group/nacos-spring-boot-project
但是这个好像不更新,spring-cloud-starter-alibaba-nacos-config一直在迭代
starer中只有一个spring.providers文件,也是spring frameword2.0中的一个扩展点,用于提供接口的实现提供者,在spring容器启动的时候也会扫描这个文件,provides: nacos-config-spring-boot-autoconfigure表示去autoconfigure这个模块

接着进入到autoconfigurate下面依旧可以看到spring.factories文件

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.alibaba.boot.nacos.config.autoconfigure.NacosConfigAutoConfiguration
org.springframework.boot.env.EnvironmentPostProcessor=\
  com.alibaba.boot.nacos.config.autoconfigure.NacosConfigEnvironmentProcessor

cloud项目借助了boostrap,那么springboot项目只能寻找其他扩展点了,这里就有一个重要的扩展点,NacosConfigEnvironmentProcessor,是spring生命周期中处于非常早期的阶段,在spring创建Envirorment之后,应用上下文创建之前,是对应用环境最后调整的机会, 所以这个时候我们可以干预配置,
重写postProcessEnvironment方法,并且ConfigFileApplicationListener里面也是根据顺序加载的,NacosConfigEnvironmentProcessor是处于最后一个加载的,

核心方法为loadConfig,主要思路跟cloud那个差不多,也是请求server端的配置,并组装为PropertySource放入Environment

在NacosUtils中,也是通过NacosConfigService获取配置,发起http请求,不过自从nacos2.0之后换成了grpc


执行完成,发现NacosPropertySources已经放到Environment里面了

环境变量准备完成,下一步就是NacosConfigAutoConfiguration了首先执行的是NacosConfigBootBeanDefinitionRegistrar,实现了ImportBeanDefinitionRegistrar可以在运行时向spring应用上下文注入额外的Bean定义,可以动态根据条件注入
这里注入的是NacosBootConfigurationPropertiesBinder
因为这个时候没有cloud包下面的@RefreshScope,只能用其他方式来实现,常用的配置为在类上添加@NacosConfigurationProperties,或者是属性上面将@NacosValue替代@Value,所以下面需要做的就是将Envirorment里的属性绑定到对应的bean上,是一个工程量比较大的活
下面开始看执行注解@EnableNacosConfig NacosConfigBeanDefinitionRegistrar

可以看到这个也是实现了ImportBeanDefinitionRegistrar接口,主要还是注册bean用的,
这里主要看registerNacosConfigBeans方法,其他的可以暂时先不看,

这里会注入几个Processor,首先第一个registerPropertySourcesPlaceholderConfigurer,其实是注册PropertySourcesPlaceholderConfigurer,是spring中的类,用于配置文件中占位符的解析工作,以${}的格式,一般springboot会自动注入,这里为了后续解析,提前让他注入进来,


然后第二个是注册NacosConfigurationPropertiesBindingPostProcessor

主要是实现了BeanPostProcessor,通过实现这个接口,可以在spring初始化bean的前后插入自定义的逻辑,值得注意的是每个bean创建和吃时候都会调用这个接口,所以这里效率不会特别高

而NacosConfigurationPropertiesBindingPostProcessor中扫描每个bean是否含有注解@NacosConfigurationProperties,如果有这个注解将environment的内容赋值给对应的bean,这样就达到了ConfigurationProperties的效果

但是事实上@ConfigurationProperties就是这么干的,最后都是使用的DataBinder

只不过NacosConfigurationproperties在绑定完属性之后,会为当前的DataCache添加一个监控器,并且发布NacosConfigEvent事件与NacosConfigMetadataEvent事件

项目中也可以监听这两个事件对配置更改之后做一些自定义的逻辑,如果有一个类上面含有NacosConfigurationProperties注解,此时已经加载完成
接下来加载 的是NacosConfigListenerMethodProcessor,一般是这样使用的,注册放在方法上,监听对应的dataId,如果对应的配置发生了变化,那么就会调用方法里面的逻辑,听着很牛逼,源码点进去看看是怎么实现的

AnnotationListenerMethodProcessor首先监听的是ContextRefreshedEvent事件,当这个事件触发之后才开始执行,
首先通过ApplicationContext获取所有的bean,然后通过ReflectionUtils遍历查找每个bean里面是否含有注解@NacosConfigListener

再给当前的CacheData添加一个监听器,监听器里面通过反射调用目标方法,同时发布NacosConfigMetadataEvent事件,可以看的出来,@NacosConfigListener归根结底是为当前的CacheData多注册了一个监听器,也是底层框架扩展性高的原因,

当然如果不满足这个方法,可以自己往里面添加一个监听器,效果也是一样的,

接下来还有其他几个,主要看这个NacosValueAnnotationBeanPostProcessor,解析带有@NacosValue注解的属性值,查看@NacosValue发现也可以用在方法上,

实现了监听器,监听NacosConfigReceivedEvent事件, 以及实现了InstantiationAwareBeanPostProcessor

首先还是看这个postProcessBeforeInitialization,初始化之前的处理方法,处理带@NacosValue的属性以及方法


最后放入placeholderNacosValueTargetMap 中等待监听器执行,
当发生属性变化的时候,循环刚才放入的map,然后依旧是比较两个值的md5值,如果md5值不一样,再用反射进行替换

posted @ 2024-07-05 16:47  木马不是马  阅读(86)  评论(0编辑  收藏  举报