一、架构分析
Mybatis中Mapper一般只是一个接口, 那么为什么能执行数据操作的呢? 那肯定是基于代理没得说。在了解Mybatis如何实现代理前, 我们先大概看下它的架构是什么样的, 对这些关键的类有个大概的认识, 知道它所处的位置在哪里。
本篇我们只深入研究下代理层, 学习下mybatis是如何进行代理操作的, 而关于sql的最终执行, 放到下一篇执行流程中来研究。
二、源码分析
首先不要慌, 看上面这个图, Mybatis的代理流程还是比较简单的。下面主要看下每个核心的类是做什么用的。
2.1 MapperProxyFactory
- 代理工厂里面看代码是比较简单的, 就是利用Proxy创建代理对象。
- 对于已经生成的代理方法, 直接放到MethodCache缓存起来。
public class MapperProxyFactory<T> {
private final Class<T> mapperInterface;
private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();
// Jdk代理Proxy, 可以看到主要逻辑在MapperProxy中
protected T newInstance(MapperProxy<T> mapperProxy) {
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] {
mapperInterface }, mapperProxy);
}
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
}
2.2 MapperProxy
MapperProxy 的代理逻辑也非常简单, 就以下三个能力, 看图理解。
下面将核心的处理代码给挑选了出来, 增加了注释。
public class MapperProxy<T> implements InvocationHandler, Serializable {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
// Object方法直接执行
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
// 其他方法生成代理方法
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
} catch (Throwable t) {
th