多态仅为多租户隔离策略提供统一调用接口,不负责策略选择;实际隔离由运行时基于threadlocal中的租户上下文,通过工厂或objectprovider按租户标识动态获取具体实现类。

多态在多租户系统中不直接实现隔离,而是为不同租户的隔离策略提供统一调用入口。它本身不决定“该用哪个策略”,只确保“调用方式一致”。
多态是表层能力,策略分发才是核心
你定义一个 TenantIsolationStrategy 接口,所有租户专属的隔离逻辑(如字段过滤、Schema切换、数据源路由)都实现它。但具体用哪一个,不由多态自动选,而由运行时根据租户上下文决定。
租户上下文必须前置建立
在请求入口(Filter 或 Interceptor)中提取租户标识(如 X-Tenant-ID 头或子域名),并存入 ThreadLocal<tenantcontext></tenantcontext>。后续所有隔离策略都从这里读取 tenantId,避免参数层层透传。
策略选择靠工厂或条件装配,不是靠多态匹配
- ✅ 正确做法:用
ObjectProvider<tenantisolationstrategy></tenantisolationstrategy>按 bean 名查找,例如"tenant-a-isolation" - ✅ 或自定义工厂类:内部查映射表
{ "acme": ColumnBasedStrategy.class, "vip": SchemaRoutingStrategy.class },再applicationContext.getBean(...)实例化 - ❌ 错误理解:“写个
strategy.doIsolate()就能自动调到 vip 版本”——没有上下文感知,多态无法区分租户
每种策略实现对应一种隔离方式,接口保持统一语义
public interface TenantIsolationStrategy {
void applyToQuery(QueryBuilder builder); // 统一方法名
void enforceOnDataSource(); // 统一方法名
}
-
ColumnBasedStrategy实现里追加WHERE tenant_id = ? -
SchemaRoutingStrategy实现里调用DataSourceContextHolder.set("schema_vip") -
DatabaseRoutingStrategy实现里触发AbstractRoutingDataSource切库
这样上层代码只认接口,不关心租户细节;新增租户只需加一个实现类 + 配置映射,不改调用方。
关键提醒:多态不能替代数据层隔离机制
- 行级隔离需 MyBatis-Plus 多租户插件自动注入
tenant_id条件 - Schema 级隔离需
AbstractRoutingDataSource根据当前租户动态返回数据源 - 数据库级隔离需独立连接池 + 动态注册数据源
多态只是把上述能力“包装成同一种样子”,让业务代码干净调用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











