抽象类是封装动态数据源路由骨架的最佳选择,它统一管理ThreadLocal上下文、生命周期及fallback流程,强制子类实现determineDataSourceKey()和buildTargetDataSources(),提供可扩展钩子方法,并支持注解继承简化业务实现。

抽象类是统一定义动态数据源路由骨架最自然的选择——它既能封装通用路由逻辑和上下文管理,又能把“由谁决定用哪个库”这个关键点留给子类灵活实现。
用抽象类封装路由上下文与生命周期管理
把 ThreadLocal 的存取、清理、键值校验等共用操作收进抽象类,避免每个具体路由类重复写样板代码。
- 定义 protected 抽象方法 determineDataSourceKey(),强制子类提供业务判断逻辑(比如根据注解、事务只读属性或方法名前缀)
- 在抽象类中实现 setDataSource(String key)、clearDataSource() 和 getDataSourceKey(),全部基于统一的 ThreadLocal 实例
- 在 clearDataSource() 中加入日志或断言,防止子类忘记清理导致线程复用污染
把数据源注册与 fallback 机制固化为模板流程
AbstractRoutingDataSource 的核心行为(查 map、回退 default)不应由子类重写,而应由抽象类封装为 final 方法。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 抽象类继承 AbstractRoutingDataSource,声明 protected abstract Map<Object, DataSource> buildTargetDataSources(); 让子类负责组装多数据源
- 在构造器中调用 buildTargetDataSources() 并注入 targetDataSources 和 defaultTargetDataSource,确保初始化一次到位
- 重写 determineCurrentLookupKey() 为 final 方法:先调用 getDataSourceKey(),若为空则触发钩子方法 onMissingKey()(默认抛异常,子类可覆盖)
用钩子方法支持柔性扩展点
不是所有场景都需要相同的数据源策略,比如测试环境可能全走 H2,灰度环境需按用户 ID 哈希分流——这些差异不破坏主流程,适合用钩子。
立即学习“Java免费学习笔记(深入)”;
- 提供 protected boolean shouldUseDefaultWhenMissing() { return false; },子类可返回 true 启用兜底
- 提供 protected Object normalizeKey(Object rawKey) { return rawKey; },用于统一转换字符串 key 或加前缀
- 提供 protected void onDataSourceSelected(String key) { },供子类打监控埋点或记录审计日志
配合注解继承简化子类实现
结合 dynamic-datasource 等框架的注解继承能力,让抽象基类承担数据源语义,子类专注业务。
- 在抽象类上标注 @DS("master"),其所有非重写方法默认走主库;子类可局部覆盖,如 @DS("slave") public List<User> findAll() { ... }
- 定义自定义注解 @MasterOnly 或 @ReadPreference,通过 AOP + 抽象类上下文工具联动,比硬编码更清晰
- 子类只需继承抽象路由类 + 实现 buildTargetDataSources(),其余全部复用,连 determineCurrentLookupKey 都不用碰


















