跳转至

MyBatis 用到哪些设计模式?

一、建造者模式(Builder)

SqlSessionFactoryBuilderXMLConfigBuilderXMLMapperBuilder 都用建造者模式解析复杂的 XML 配置,把"配置加载"与"对象构建"分离。

SqlSessionFactory factory = new SqlSessionFactoryBuilder()
    .build(inputStream);

二、工厂模式

  • SqlSessionFactory:工厂接口,生产 SqlSession
  • MapperProxyFactory:为每个 Mapper 接口生产代理实例。
SqlSession session = factory.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);

三、代理模式

MyBatis 不需要写 Mapper 实现类,接口方法调用被 MapperProxy(实现 InvocationHandler)拦截,最终执行 SQL:

public class MapperProxy<T> implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) {
        // 转成 MapperMethod,执行 SqlSession.select/update
    }
}

四、模板方法

BaseExecutor 实现了"获取连接、参数绑定、结果集处理"流程,把 doUpdate/doQuery 交给子类:

  • SimpleExecutor
  • ReuseExecutor
  • BatchExecutor

五、适配器

ParameterHandlerResultSetHandler 适配不同的 JDBC 类型与 Java 类型。

六、装饰器 / 包装器

Cache 接口有多种实现,层层包装:

LruCache -> FifoCache -> LoggingCache -> SynchronizedCache

这是典型的装饰器模式,给原始 Cache 动态加 LRU、日志、同步等能力。

七、责任链

插件(Interceptor)用责任链包装四大对象(Executor、ParameterHandler、ResultSetHandler、StatementHandler):

interceptorChain.pluginAll(target);
// 每个插件都包装一次,形成链

八、策略模式

  • LanguageDriver:处理 SQL 脚本。
  • Logging:选择用 Log4j、Slf4j 还是 JDK logging。
  • TypeHandler:每种 Java 类型与 JDBC 类型的转换策略。

九、单例

Configuration 在整个 SqlSessionFactory 中是单例。

高频追问

  • 为什么 Mapper 接口不用写实现类?因为 JDK 动态代理 MapperProxy
  • 一级缓存和二级缓存:一级是 Executor 级,SqlSession 关闭就没;二级是 Mapper 级,跨 SqlSession,但生产环境几乎不用(容易脏数据)。