Mybatis Mapper 接口工作原理 3 - mapper 代理对象执行

当调用 Mapper 接口的方法时,实际上调用的是代理对象的方法。由于代理对象是通过 JDK 动态代理生成的,因此方法调用会被转发给 InvocationHandlerinvoke 方法。

1 MapperProxy.invoke() 的源码分析

MapperProxyInvocationHandler 的实现类,invoke 方法的实现如下:

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 如果是 Object 类的方法(如 toString、hashCode),直接调用
    if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
    }
    // 获取 MapperMethod 并执行
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
}
  • cachedMapperMethod(method):缓存 MapperMethod 对象,避免重复创建。
  • mapperMethod.execute(sqlSession, args):调用 MapperMethodexecute 方法执行 SQL 查询。

2. 获取 MapperMethod

private MapperMethod cachedMapperMethod(Method method) {
    // 从 Mapper 接口的方法中缓存该方法的解析结果
    MapperMethod mapperMethod = methodCache.get(method);
    if (mapperMethod == null) {
        mapperMethod = new MapperMethod(method, configuration);
        methodCache.put(method, mapperMethod);
    }
    return mapperMethod;
}

public MapperMethod(Method method, Configuration configuration) {
    // 获取方法的映射信息
    this.configuration = configuration;
    this.method = method;

    // 获取方法上的注解或 XML 配置,进行解析
    this.sqlCommand = getSqlCommand();
    this.parameterType = getParameterType();
    this.resultType = getResultType();
    this.mapperMethodInvoker = buildMethodInvoker();
}

3. MapperMethod.execute() 的源码分析

MapperMethod 封装了 Mapper 接口方法的执行逻辑,execute 方法的实现如下:

public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
        case INSERT:
            result = sqlSession.insert(command.getName(), args);
            break;
        case UPDATE:
            result = sqlSession.update(command.getName(), args);
            break;
        case DELETE:
            result = sqlSession.delete(command.getName(), args);
            break;
        case SELECT:
            if (method.returnsVoid() && method.hasResultHandler()) {
                executeWithResultHandler(sqlSession, args);
                result = null;
            } else if (method.returnsMany()) {
                result = executeForMany(sqlSession, args);
            } else if (method.returnsMap()) {
                result = executeForMap(sqlSession, args);
            } else {
                result = executeForOne(sqlSession, args);
            }
            break;
        default:
            throw new BindingException("Unknown execution method for: " + command.getName());
    }
    return result;
}

4. 总结

1. sqlSession.getMapper() 获取到的是什么?

获取到的是 Mapper 接口的代理对象,这个代理对象是通过 JDK 动态代理生成的,核心类是 MapperProxy

2. 调用 mapper 方法执行原理

  1. 因为 mapper 实际的对象是 JDK 动态代理生成的,所以调用 mapper 的方法会被拦截,会触发 MapperPoxy.invoke() 方法
  2. MapperPoxy.invoke() 中会调用 MapperMethod.execute() 方法(被调用的方法会被封装成 MapperMethod 对象)
  3. MapperMethod.execute() 会调用 SqlSession 的方法
  4. SqlSession 的工作原理请看 这里
posted @   CyrusHuang  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示