多态本身不直接实现数据隔离或动态装载,它只是面向对象中“同一接口、不同行为”的运行时机制;真正起作用的是租户上下文+策略分发+工厂/条件装配,多态仅提供统一调用表层能力。

多态本身不直接实现数据隔离或动态装载,它只是面向对象中“同一接口、不同行为”的运行时机制。真正起作用的是租户上下文 + 策略分发 + 工厂/条件装配,多态只是让这些策略能被统一调用的表层能力。
下面从实际落地角度说明怎么做:
租户上下文是动态装载的前提
必须在请求入口(如Filter、Interceptor)中提取租户标识(Header、JWT、子域名等),并绑定到当前线程或请求作用域:
一款AI音频处理工具,主要用于MiniMax统一媒体生成技能,用于TokenPlan工作流。当用户要求生成音频、语音、TTS、旁白、图片、插图、姿势等媒体内容时使用,适合需要提升相关任务效率的用户。
- 使用
ThreadLocal<tenantcontext></tenantcontext>或 Spring 的RequestScope保存tenantId - 所有后续操作(DAO、Service、缓存)都从该上下文中读取租户信息
- 避免在方法参数里反复传
tenantId,否则容易遗漏或误用
多态用于封装租户专属行为,而非控制路由
定义统一接口,不同租户对应不同实现类,但实例化不由多态决定,而由策略选择:
public interface OrderRepository {
List<order> findAll();
void save(Order order);
}
@Component("basicOrderRepo")
public class BasicOrderRepository implements OrderRepository { ... }
@Component("premiumOrderRepo")
public class PremiumOrderRepository implements OrderRepository { ... }</order>
✅ 正确用法:通过工厂或 ObjectProvider 按租户查 Bean
❌ 错误理解:“用 OrderRepository::new + 多态自动选实现”——这无法编译,也不具备上下文感知能力
动态装载靠策略分发,不是靠方法引用
Spring 提供多种运行时按租户选实现的方式:
-
ObjectProvider<orderrepository></orderrepository>:根据 bean 名称(如"acmeOrderRepo")查找 -
@ConditionalOnProperty或@Profile:配合配置中心动态启用某租户专用实现 - 自定义
OrderRepositoryFactory:内部查tenantId → repoType映射表,返回对应实例 -
ApplicationContext.getBean(String name, Class<t> type)</t>:bean 名可拼接租户ID(如tenantId + "OrderRepo")
数据隔离要落到每一层,多态只是辅助表达
-
DAO 层:租户字段(如
tenant_id)自动注入 & 自动过滤(MyBatis-Plus 多租户插件) -
数据源层:
AbstractRoutingDataSource根据tenantId切换连接池(独立库 / 独立 Schema) -
对象建模层:实体继承
TenantEntity,tenantId强制构造、不可变、参与主键与 equals/hashCode -
服务层:每个
OrderService实例持有一个tenantId,所有方法默认作用于该租户,不接受外部传入
不复杂但容易忽略










