在 Java 的 SPI 机制中,通常会在 META-INF/services/ 目录下定义接口和实现。在 Spring Boot 中,这一机制被应用在自动配置上,其入口文件是 spring.factories 。
在这个项目中,该文件的内容是:
org.springframework.boot.autoconfigure.
EnableAutoConfiguration=cn.yyb.wrench.
dynamic.config.center.config.
DynamicConfigCenterRegisterAutoConfig,
cn.yyb.wrench.dynamic.config.center.
config.DynamicConfigCenterAutoConfig
这行配置告诉 Spring Boot,在应用启动时,需要自动加载并处理 DynamicConfigCenterRegisterAutoConfig 和 DynamicConfigCenterAutoConfig 这两个配置类。
整个动态配置的实现流程可以分为 初始化 和 动态更新 两个阶段,由这两个自动配置类分工完成。 阶段一:初始化与Bean的代理
-
基础设施初始化 ( DynamicConfigCenterRegisterAutoConfig )
- 当 Spring Boot 加载
DynamicConfigCenterRegisterAutoConfig时,它会负责创建所有核心组件的 Bean:- redissonClient : 创建一个
redissonClientBean,用于连接和操作 Redis。 - dynamicConfigCenterService : 创建
IDynamicConfigCenterService接口的实现类DynamicConfigCenterService的 Bean,这是动态配置的核心服务。 - dynamicConfigCenterAdjustListener : 创建一个消息监听器
DynamicConfigCenterAdjustListener,用于监听 Redis 中的配置变更消息。 - dynamicConfigCenterRedisTopic : 获取一个 Redis 的 RTopic 对象,并将上述监听器注册到这个主题上。
- redissonClient : 创建一个
- 当 Spring Boot 加载
-
Bean 后置处理与代理创建 ( DynamicConfigCenterAutoConfig )
DynamicConfigCenterAutoConfig实现了 BeanPostProcessor 接口,这是一个 Bean 的后置处理器。- 在 Spring 容器初始化完每一个 Bean 之后,都会调用它的
postProcessAfterInitialization方法。 - 在这个方法内部,它会调用 dynamicConfigCenterService.proxyObject(bean) 。
- proxyObject 方法会检查当前 Bean 中是否包含被 @DCCValue 注解标记的字段。如果存在,它会使用 CGLIB 为这个 Bean 创建一个代理对象,并替换掉 Spring 容器中原有的 Bean 实例。同时,它会从 Redis 中拉取该字段的初始值并赋给它。 至此,所有带有 @DCCValue 注解的 Bean 都已经被代理,并且它们的被注解字段也获得了初始值。 阶段二:配置的动态更新
-
发布变更
- 当外部系统(例如您的测试代码 ApiTest.test_publish )向 Redis 的特定主题( DYNAMIC_CONFIG_CENTER_REDIS_TOPIC_test-system )发布一个 AttributeVO 消息时,代表一个配置项发生了变更。
-
监听与处理
- 之前注册的
DynamicConfigCenterAdjustListener会接收到这个消息,并触发其 onMessage 方法。
- 之前注册的
-
属性更新
- onMessage 方法会调用 dynamicConfigCenterService.adjustAttributeValue(attributeVO) 。
- adjustAttributeValue 方法会根据传入的 AttributeVO (包含了属性名和新的值),在之前缓存的代理 Bean 集合( dccBeanGroup )中找到对应的 Bean 实例,然后通过反射直接修改该 Bean 实例中对应字段的值。
总的来说,该项目的 SPI 机制就是利用 Spring Boot 的自动配置,通过 spring.factories 文件自动加载配置类。这些配置类完成了 “初始化基础设施 -> 扫描并代理目标Bean -> 监听消息 -> 动态更新属性” 的完整闭环,从而实现了对 @DCCValue 注解字段的动态配置管理。