Skip to content

MyBatis 源码分析

  深入 MyBatis 源码,理解核心组件的工作机制,掌握 Mapper 代理、SQL 执行、插件拦截等底层原理。

一、源码架构全景

MyBatis 核心包结构:

org.apache.ibatis
├── session/          → SqlSession、SqlSessionFactory
├── executor/         → Executor 执行器
├── mapping/          → MappedStatement、BoundSql
├── scripting/        → 动态 SQL 解析
├── binding/          → Mapper 代理绑定
├── builder/          → 配置解析(XML 解析)
├── plugin/           → 插件机制
├── cache/            → 缓存
├── transaction/      → 事务管理
├── datasource/       → 数据源
├── reflection/       → 反射工具
├── logging/          → 日志
└── type/             → 类型处理器

二、配置文件解析流程

mybatis-config.xml 解析流程:

  SqlSessionFactoryBuilder.build(InputStream)


  XMLConfigBuilder.parse()

      ├── 解析 <properties>     → 变量
      ├── 解析 <settings>       → Configuration 全局设置
      ├── 解析 <typeAliases>    → 别名注册
      ├── 解析 <typeHandlers>   → 类型处理器注册
      ├── 解析 <plugins>        → 拦截器链
      ├── 解析 <environments>   → 数据源 + 事务管理器
      ├── 解析 <databaseIdProvider> → 数据库厂商标识
      └── 解析 <mappers>        → 解析 Mapper XML


  返回 Configuration 对象


  创建 DefaultSqlSessionFactory(Configuration)

关键类:

XMLConfigBuilder       → 解析 mybatis-config.xml
XMLMapperBuilder       → 解析每个 Mapper XML
XMLStatementBuilder    → 解析每个 <select>/<insert>/<update>/<delete>
MapperAnnotationBuilder → 解析 Mapper 接口注解

三、Mapper 代理原理

问题:UserMapper 是一个接口,没有实现类,为什么能执行 SQL?

答案:MyBatis 通过 JDK 动态代理  生成 MapperProxy 代理对象
java
// 源码核心流程(简化版)

// ① 获取 Mapper 时创建代理
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    // MapperRegistry
    MapperProxyFactory<T> mapperProxyFactory = knownMappers.get(type);
    return mapperProxyFactory.newInstance(sqlSession);
}

// ② MapperProxyFactory 创建代理
public T newInstance(SqlSession sqlSession) {
    MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    return (T) Proxy.newProxyInstance(
        mapperInterface.getClassLoader(),
        new Class[]{mapperInterface},
        mapperProxy
    );
}

// ③ MapperProxy.invoke() 拦截所有方法调用
public Object invoke(Object proxy, Method method, Object[] args) {
    // 如果是 Object 的方法(toString、hashCode 等),直接调用
    if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
    }
    // 缓存 MapperMethod
    MapperMethod mapperMethod = cachedMapperMethod(method);
    // 执行 SQL
    return mapperMethod.execute(sqlSession, args);
}

// ④ MapperMethod.execute() 分发到 SqlSession
public Object execute(SqlSession sqlSession, Object[] args) {
    switch (command.getType()) {
        case INSERT:  return sqlSession.insert(command.getName(), param);
        case UPDATE:  return sqlSession.update(command.getName(), param);
        case DELETE:  return sqlSession.delete(command.getName(), param);
        case SELECT:
            if (returnsMany) return sqlSession.selectList(command.getName(), param);
            if (returnsMap)   return sqlSession.selectMap(command.getName(), param, ...);
            return sqlSession.selectOne(command.getName(), param);
    }
}
执行流程总结:

  接口方法调用 → MapperProxy.invoke() → MapperMethod.execute()
    → SqlSession.xxx() → Executor.xxx() → StatementHandler → JDBC

四、Executor 源码

java
// Executor 接口
public interface Executor {
    int update(MappedStatement ms, Object parameter);
    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds,
                       ResultHandler resultHandler);
    void commit(boolean required);
    void rollback(boolean required);
    Transaction getTransaction();
    CacheKey createCacheKey(MappedStatement ms, Object parameter, ...);
    // ...
}

BaseExecutor 一级缓存实现:

java
// BaseExecutor.query() 一级缓存逻辑(简化版)
public <E> List<E> query(MappedStatement ms, Object parameter, ...) {
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);

    // ① 先查一级缓存
    List<E> list = (List<E>) localCache.getObject(key);
    if (list != null) {
        return list;
    }

    // ② 缓存没命中,查数据库
    list = queryFromDatabase(ms, parameter, rowBounds, ...);

    // ③ 放入一级缓存
    localCache.putObject(key, list);
    return list;
}

// 增删改清空缓存
public int update(MappedStatement ms, Object parameter) {
    clearLocalCache();  // 清空一级缓存
    return doUpdate(ms, parameter);
}

CachingExecutor 二级缓存实现:

java
// CachingExecutor.query() 二级缓存逻辑(简化版)
public <E> List<E> query(MappedStatement ms, Object parameter, ...) {
    Cache cache = ms.getCache();  // 获取二级缓存
    if (cache != null) {
        CacheKey key = createCacheKey(ms, parameter, ...);

        // ① 先查二级缓存
        List<E> list = (List<E>) cache.getObject(key);
        if (list != null) {
            return list;
        }
    }

    // ② 二级缓存没命中,委托给 BaseExecutor(一级缓存 + 数据库)
    return delegate.query(ms, parameter, ...);
}

五、StatementHandler 源码

java
// StatementHandler 接口
public interface StatementHandler {
    Statement prepare(Connection connection, Integer transactionTimeout);
    void parameterize(Statement statement);  // 设置参数
    int update(Statement statement);
    <E> List<E> query(Statement statement, ResultHandler resultHandler);
    BoundSql getBoundSql();
}

执行流程:

java
// SimpleExecutor.doQuery() 简化版
public <E> List<E> doQuery(MappedStatement ms, Object parameter, ...) {
    // ① 创建 StatementHandler
    StatementHandler handler = configuration.newStatementHandler(...);

    // ② 创建 Statement(PreparedStatement/CallableStatement)
    Statement stmt = prepareStatement(handler, ms.getStatementLog());

    // ③ 设置参数
    handler.parameterize(stmt);

    // ④ 执行 SQL 并处理结果
    return handler.query(stmt, resultHandler);
}

private Statement prepareStatement(StatementHandler handler, Log statementLog) {
    // 获取连接
    Connection connection = getConnection(statementLog);
    // 调用 prepare
    Statement stmt = handler.prepare(connection, transaction.getTimeout());
    // 设置参数
    handler.parameterize(stmt);
    return stmt;
}

六、插件拦截原理

java
// Plugin.wrap() 创建代理
public static Object wrap(Object target, Interceptor interceptor) {
    // 获取 @Signature 注解
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);

    Class<?> type = target.getClass();
    // 获取目标类所有接口
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);

    if (interfaces.length > 0) {
        // 创建 JDK 动态代理
        return Proxy.newProxyInstance(
            type.getClassLoader(),
            interfaces,
            new Plugin(target, interceptor, signatureMap)
        );
    }
    return target;
}

// Plugin.invoke() 拦截方法调用
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 判断当前方法是否是需要拦截的方法
    Set<Method> methods = signatureMap.get(method.getDeclaringClass());
    if (methods != null && methods.contains(method)) {
        // 调用 Interceptor.intercept()
        return interceptor.intercept(new Invocation(target, method, args));
    }
    // 不是拦截的方法,直接调用
    return method.invoke(target, args);
}
责任链包装过程:

  Configuration.newExecutor()
    → executor = new SimpleExecutor()  // 创建原始 Executor
    → executor = (Executor) interceptorChain.pluginAll(executor)
      → 遍历所有插件,逐层包装
      → executor = Plugin.wrap(executor, interceptor1)
      → executor = Plugin.wrap(executor, interceptor2)
      → ...

  最终得到的是一个多层代理对象:
    Plugin2 → Plugin1 → SimpleExecutor

七、核心类关系图

SqlSessionFactory
  └── creates → SqlSession
                  ├── getMapper() → MapperProxy(动态代理)
                  └── delegates to → Executor
                                       ├── CachingExecutor(二级缓存)
                                       └── delegates to → BaseExecutor(一级缓存)
                                                             ├── SimpleExecutor
                                                             ├── ReuseExecutor
                                                             └── BatchExecutor
                                                                   └── uses → StatementHandler
                                                                                 ├── SimpleStatementHandler
                                                                                 ├── PreparedStatementHandler
                                                                                 └── CallableStatementHandler
                                                                                       ├── ParameterHandler(参数处理)
                                                                                       └── ResultSetHandler(结果处理)

八、速记总结

源码核心流程:

  配置文件解析 → Configuration → SqlSessionFactory
      → SqlSession → Executor → StatementHandler → JDBC

  Mapper 代理:JDK 动态代理 → MapperProxy → MapperMethod → SqlSession
  缓存:CachingExecutor(二级)→ BaseExecutor(一级)
  插件:Plugin.wrap() 创建层层代理

速记口诀:
  解析配置建工厂,会话执行委托器,
  Mapper 代理拦截调,缓存两层查执行,
  插件层层包装类,StatementHandler 真干活。

九、面试要点

问题答案要点
Mapper 怎么不写实现类就能执行?JDK 动态代理,MapperProxy 拦截方法调用
一级缓存存在哪?BaseExecutor 的 localCache(PerpetualCache)
插件链怎么实现的?责任链模式,Plugin.wrap() 层层代理
Executor 的执行流程?Executor → StatementHandler → ParameterHandler → JDBC → ResultSetHandler