Mybatis的Mapper底层原理

总的来说是通过动态代理。动态代理的功能就是通过拦截器方法回调(invokeHandler),达到增强目标对象的目的。看下面代码,很关键一点就是InvocationHandler包含target对象。在invoke方法中会调用target的方法。

public class HelloWordProxy extends InvokeHandler{
  // 真正的本体
  private Object target;

  public Object bind(Object target) {
    this.target= target;
    return Proxy.newInstance(taget.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    
  }

  @Overrride
  public Object invoke(Object proxy, Method method, Object[] args) {
    System.out.println("before execute real target method");
    result = method.invoke(target, args);
    System.out.println("after execute real target method");
    return result;
  }
}

在Mybatis里面,会定义一个MapperProxy(实现InvocationHandler),先看MapperProxyFactory:

public class MapperProxyFactory<T> {

...
  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<T>(sqlSession, mapperInteface, methodCache);
    return newInstance(mapperProxy);
  }
}

重点关注上面的public方法,可以看出MapperProxy是用sqlSession创建的,并且Proxy.newInstance()方法的第三个参数就是这个MapperProxy对象本身(这个符合动态代理的基本创建方法)。

再看MapperProxy的执行代码:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MapperProxy implements InvocationHandler {

	@SuppressWarnings("unchecked")
	public <T> T newInstance(Class<T> clz) {
		return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] { clz }, this);
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if (Object.class.equals(method.getDeclaringClass())) {
			try {
				// 诸如hashCode()、toString()、equals()等方法,将target指向当前对象this
				return method.invoke(this, args);
			} catch (Throwable t) {
			}
		}
		MapperMethod mapperMethod = cachedMapperMethod(method);
		return mepperMethod.execute(sqlSession, args);
	}
}

method.invoke(this, args) 第一个参数往往是target, 而这里的target就是MapperProxy自己。所里这里起到的并不是增强target的功能,而是“取代”target的功能。而事实上,在Mybatis里面,从来就没出现target,target只是个占位符。

还要注意:最后mapperMethod.execute(sqlSesison, args)也很有意思,他是后序执行sql语句的入口,它会调用sqlSession的各种数据库操作方法,而这些方法就会去调用sqlSession的四大组件。这个会在后序的sql执行过程中详细介绍。



  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis 是一个 Java 的持久层框架,它通过 SQL 映射文件(`.xml` 或者 `.java`)将 Java 对象和数据库操作解耦。MyBatis底层原理主要包括以下几个关键组件: 1. **SqlSessionFactory**:它是 MyBatis 应用的起点,负责创建并管理 SqlSession 对象。SqlSessionFactory 通过读取配置文件(例如 `mybatis-config.xml`),加载所有的数据库连接信息。 2. **SqlSession**:每个 SqlSession 实例代表一次数据库交互的上下文。它是线程安全的,但通常在方法执行完毕后关闭,避免资源泄露。SqlSession 提供了执行 SQL、查询、更新和删除操作的方法。 3. **Mapper接口**:开发者定义的接口,其中包含了一系列的公共方法,对应数据库中的表操作。这些接口通常映射到 XML 文件或注解形式的 SQL 语句。 4. **XML 映射文件**或**Java 注解**:用于定义 SQL 查询和参数映射。它们将 SQL 语句与 Mapper 接口的方法关联起来,当调用接口方法时,MyBatis 会动态生成并执行相应的 SQL。 5. **StatementHandler**:处理具体的 SQL 执行,包括解析 SQL、准备参数、执行 SQL 以及处理结果集。MyBatis 使用预编译语句来提高性能和安全性。 6. **TypeHandler**:负责数据类型的转换,当查询的结果类型与 Java 对象的属性类型不匹配时,TypeHandler 会起到桥梁作用。 7. **缓存机制**:MyBatis 提供了二级缓存,可以存储查询结果,以减少对数据库的重复查询。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值