provides 语法实现模块化平滑接入的关键在于“契约抽象”和“运行时绑定”,通过声明服务能力而非实现细节,支持多存储引擎按需加载、互不干扰、可插拔替换。

直接用 provides 语法实现模块化平滑接入,关键不在语法本身,而在它所承载的“契约抽象”和“运行时绑定”能力。它不是配置开关,而是让不同存储引擎(如 Hologres、TDStore、ShardingSphere-JDBC、Tablestore)在统一接口下按需加载、互不干扰、可插拔替换的基础设施语言。
明确 provides 的定位:它声明“我能提供什么能力”,而非“我怎么实现”
在 Java 生态(尤其是基于 Spring Boot 或 AREE 的 Agent 运行时),provides 常见于模块描述符(如 module-info.java)、SPI 配置文件(META-INF/services/xxx)或现代依赖注入框架的声明式注册中。它的作用是:
- 向容器声明本模块提供的服务类型(例如:
DataSourceProvider、RetrievalSkill、QueryOptimizer) - 附带元数据(如
engine="hologres"、mode="multi-tenant"、protocol="pgwire")用于条件筛选 - 不暴露具体类名或连接细节,只暴露能力契约,解耦调用方与实现方
实战四步:从变量驱动到模块加载
以“多租户场景下动态切换 Hologres / TDStore / ShardingSphere-JDBC”为例:
-
定义统一能力接口:比如
TenantDataSourceProvider,含方法DataSource getForTenant(String tenantId)和String getEngineName() -
各引擎实现模块独立声明 provides:
- Hologres 模块在
META-INF/services/com.example.TenantDataSourceProvider中写入:com.hologres.HologresTenantProvider,并在MANIFEST.MF或application.yml中标注provides.engine: hologres - TDStore 模块同理提供
com.tdstore.TDTenantProvider,标注provides.engine: tdstore - ShardingSphere-JDBC 模块提供
com.shardingsphere.ShardingTenantProvider,标注provides.mode: sharding-jdbc
- Hologres 模块在
-
运行时按变量驱动加载:启动时读取配置项
storage.engine=hologres或multi-tenancy.strategy=database,再结合 Spring Boot 的@ConditionalOnProperty或 AREE 的EngineRouter,仅激活匹配provides元数据的模块 -
平滑切换靠“无状态契约”+“懒初始化”:所有 Provider 实现都遵循同一生命周期(init/close)、同一错误处理策略;切换引擎只需改配置、重启(或热重载),无需修改业务代码——因为业务只依赖
TenantDataSourceProvider接口
适配不同技术栈的 provides 表达方式
不必拘泥语法形式,核心是“可发现 + 可过滤 + 可替换”:
-
Java Module System:
module com.hologres.engine { provides com.example.TenantDataSourceProvider with com.hologres.HologresTenantProvider; } -
SPI + Properties:在
resources/application-dev.yml中设storage.provider.class: hologres,启动时扫描所有TenantDataSourceProvider实现,按该值匹配构造器参数或注解 -
AREE / Agentic Runtime:每个模块打包为
.agentpkg,内含provides.json描述技能能力(如"retrieval": {"engine": "tablestore", "maxChunks": 10}),Agent 调度器按 query intent 自动路由 -
Hologres CLI Skills:CLI 插件通过
hologres-cli skill list --provides=optimize,explain,profile暴露能力,IDE Copilot 根据当前 SQL 类型自动选用对应 Skill 模块
避坑要点:变量驱动 ≠ 魔法切换
真正平滑的前提是收敛差异:
- 所有存储引擎模块必须对齐租户上下文传递方式(如 ThreadLocal +
CurrentTenantIdentifierResolver) - 连接池配置需标准化(HikariCP/Druid/DBCP2 的通用参数映射到
TenantDataSourceProperties.ConnectionOptions) - 异常体系要归一(把
PSQLException、TDStoreException、ShardingSQLException统一封装为TenantDataAccessException) - 监控指标命名统一(如
tenant_datasource_acquire_time_ms{engine="hologres",tenant="t-001"})


















