MyBatis BaseExecutor 模板方法模式与策略模式详解
📌 MyBatis BaseExecutor 模板方法模式与策略模式详解
BaseExecutor 是 MyBatis Executor 体系的核心抽象类,它通过模板方法模式(Template Method Pattern)定义查询和更新的执行骨架,通过策略模式(Strategy Pattern)动态切换 SimpleExecutor、ReuseExecutor、BatchExecutor 三种执行策略。面试中经常被问到:"MyBatis 用了哪些设计模式?" BaseExecutor 就是模板方法模式与策略模式结合的经典案例。
1️⃣ 问题背景
在 MyBatis 中,所有 SQL 最终都会被 Executor 执行。
例如:
或者:
这些 SQL 的执行逻辑其实非常类似:
- 创建 Statement
- 参数绑定
- 执行 SQL
- 结果集映射
- 缓存处理
- 事务控制
如果每种 Executor 都重复实现这些流程,将会出现大量重复代码。
同时,不同 Executor 的执行方式又有所不同:
- SimpleExecutor 每次创建新 Statement
- ReuseExecutor 复用 Statement
- BatchExecutor 支持批量提交
因此 MyBatis 需要一种设计:
这正是模板方法模式和策略模式发挥作用的地方。
2️⃣ 核心原理
Executor继承体系
│
├── BaseExecutor
│ │
│ ├── SimpleExecutor
│ ├── ReuseExecutor
│ └── BatchExecutor
│
└── CachingExecutor
Executor 是顶层接口。
BaseExecutor 实现大部分通用逻辑。
SimpleExecutor、ReuseExecutor、BatchExecutor 负责实现差异化逻辑。
CachingExecutor 则属于装饰器模式,在 Executor 外层增加二级缓存功能。
3️⃣ 数据结构分析
BaseExecutor核心属性
其中:
- Transaction:事务对象
- localCache:一级缓存
- localOutputParameterCache:存储存储过程参数
- Configuration:全局配置
- queryStack:嵌套查询层级
一级缓存结构
BaseExecutor 内部维护一级缓存 HashMap。
同一个 SqlSession 内重复查询时直接返回缓存结果。
4️⃣ 算法分析
BaseExecutor查询算法
query() 方法执行过程:
│
├── 创建CacheKey
├── 查询一级缓存
├── 命中直接返回
│
└── 未命中
│
▼
queryFromDatabase()
│
▼
doQuery()
时间复杂度:
- 缓存命中:O(1)
- 缓存未命中:O(SQL执行时间)
由于优先查缓存,大多数业务场景可以显著减少数据库访问次数。
5️⃣ 执行流程
模板方法模式分析
BaseExecutor 中最经典的方法:
clearLocalCache();
return doUpdate(...);
}
这里 update() 已经固定了执行流程:
- 清空缓存
- 执行更新
而具体如何更新,交给子类实现:
再看 query():
查询一级缓存
缓存未命中
queryFromDatabase()
}
最终执行:
该方法由子类实现。
模板方法模式特点
子类实现具体步骤
流程不可修改
细节可以扩展
这就是标准模板方法模式。
6️⃣ 实际案例
SimpleExecutor
每次执行 SQL 都创建新的 Statement。
createStatement()
查询2
createStatement()
特点:
- 实现简单
- 资源占用低
- 频繁创建对象
ReuseExecutor
内部维护 StatementMap。
SQL2 → Statement2
再次执行相同 SQL:
减少数据库资源消耗。
BatchExecutor
适用于批量插入场景。
insert user2
insert user3
insert user4
flushStatements()
统一提交到数据库。
性能提升非常明显。
7️⃣ 优缺点分析
✅ 模板方法模式优点
- 消除重复代码
- 统一执行流程
- 提高扩展能力
- 符合开闭原则
- 降低维护成本
❌ 模板方法模式缺点
- 继承层次较深
- 父类职责较重
- 修改模板影响所有子类
✅ 策略模式优点
- 执行策略灵活切换
- 避免大量if else
- 扩展新Executor简单
- 符合单一职责原则
❌ 策略模式缺点
- 类数量增加
- 调用链更复杂
8️⃣ 面试常见问题
BaseExecutor用了什么设计模式?
为什么说BaseExecutor是模板方法模式?
因为:
- update()定义固定流程
- query()定义固定流程
- doUpdate()交给子类实现
- doQuery()交给子类实现
符合:
延迟部分实现到子类
为什么说Executor用了策略模式?
Executor接口定义统一行为:
- update()
- query()
- commit()
- rollback()
具体执行策略:
- SimpleExecutor
- ReuseExecutor
- BatchExecutor
运行时可以自由切换。
Executor默认实现是哪一个?
MyBatis 默认创建 SimpleExecutor。
CachingExecutor属于什么模式?
属于装饰器模式(Decorator Pattern)。
其作用是在 Executor 外层增加二级缓存能力。
MyBatis还有哪些经典设计模式?
- 工厂模式(SqlSessionFactory)
- 代理模式(MapperProxy)
- 模板方法模式(BaseExecutor)
- 策略模式(Executor)
- 装饰器模式(CachingExecutor)
- 建造者模式(XMLConfigBuilder)
- 责任链模式(InterceptorChain)
- 适配器模式(LogAdapter)
9️⃣ 总结
📌 BaseExecutor是MyBatis执行器体系核心抽象类。
📌 模板方法模式:BaseExecutor定义query()、update()等固定执行流程,doQuery()、doUpdate()交给子类实现。
📌 策略模式:SimpleExecutor、ReuseExecutor、BatchExecutor代表三种不同SQL执行策略,运行时动态切换。
📌 SimpleExecutor:每次创建新Statement。
📌 ReuseExecutor:复用Statement减少资源开销。
📌 BatchExecutor:批量执行SQL提升吞吐量。
📌 CachingExecutor:使用装饰器模式增强Executor,实现二级缓存功能。
📌 面试高频总结:MyBatis执行器体系是模板方法模式与策略模式结合的经典案例。BaseExecutor负责定义执行骨架,SimpleExecutor、ReuseExecutor、BatchExecutor负责提供不同执行策略,这种设计既保证了代码复用,又保证了扩展灵活性,是框架源码设计中的典型范例。
相关文章
-
Spring ai的基础
在学习Spring ai先学习这几个类的作用:(问chatGpt、文言一心、 deepseek)
NEW个对象 2025-03-15
-
如果你网站突然有很多流量你该如何处理?
网站突然有大量流量的话,一般有以下俩种情况? 1、出现了热点事件。 2、网站被攻击了,比如:DDOS 那么技术上需要引入限流组件,保持系统的稳定。
NEW个对象 2024-10-21
-
MySQL 大表治理——三分钟面试标准回答
小数据量采用分批 DELETE,大数据量采用在线迁移,长期采用分区归档,历史数据采用冷热分离。真正的大表治理不是删除数据,而是构建完整的数据生命周期管理体系。
NEW个对象 2026-06-28