Mybatis Mapper 接口工作原理 3 - mapper 代理对象执行
当调用 Mapper 接口的方法时,实际上调用的是代理对象的方法。由于代理对象是通过 JDK 动态代理生成的,因此方法调用会被转发给 InvocationHandler
的 invoke
方法。
1 MapperProxy.invoke()
的源码分析
MapperProxy
是 InvocationHandler
的实现类,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)
:调用MapperMethod
的execute
方法执行 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 方法执行原理
- 因为 mapper 实际的对象是 JDK 动态代理生成的,所以调用 mapper 的方法会被拦截,会触发
MapperPoxy.invoke()
方法 MapperPoxy.invoke()
中会调用MapperMethod.execute()
方法(被调用的方法会被封装成MapperMethod
对象)MapperMethod.execute()
会调用SqlSession
的方法SqlSession
的工作原理请看 这里
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具