Mybatis Mapper接口如何找到实现类

MyBatis是优秀的持久层框架,使用时通常只需定义Mapper接口和xml文件。本文探讨了MyBatis如何找到Mapper接口的实现类,介绍了Mapper接口注册到MapperRegistry的HashMap中,以及通过JDK动态代理生成代理类完成方法调用的原理。

1、前言

       MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。我们在使用 Mybaits 进行开发 ,通常只需要定义几个 Mapper 接口,然后在编写一个 xml 文件,我们在配置文件中写好 sql , Mybatis 帮我们完成 Mapper 接口到具体实现的调用。以及将结果映射到 model bean 中。
       但是,对于 Mapper 接口,我们并没有编写其实现类!Mybatis是如何找到其实现类,进而完成具体的 CRUD 方法调用的呢?原理何在?

通常我们使用 Mybatis (Mybatis 单独使用,而不是整合 spring )的主要步骤是:

  • 构建 SqlSessionFactory ( 通过 xml 配置文件 , 或者直接编写Java代码)
  • 从 SqlSessionFactory 中获取 SqlSession
  • 从 SqlSession 中获取 Mapper
  • 调用 Mapper的方法 ,例如:userMapper.selectUser(int userId);

2、Mapper 接口是怎么找到实现类的

   2.1、Mapper 接口注册

       诸如UserMapper之类的Mapper接口被添加到了MapperRegistry 中的一个HashMap中。并以 Mapper 接口的 Class 对象作为 Key , 以一个携带Mapper接口作为属性的MapperProxyFactory 实例作为value 。

   2.2、生成Mapper接口的动态代理类

      最终是通过Proxy.newProxyInstance产生了一个UserMapper的代理对象。Mybatis 为了完成 Mapper 接口的实现,运用了代理模式。具体是使用了JDK动态代理,这个Proxy.newProxyInstance方法生成代理类的三个要素是:

  • ClassLoader —— 指定当前接口的加载器即可
  • 当前被代理的接口是什么 —— 这里就是 BlogMapper
  • 代理类是什么 —— 这里就是 MapperProxy

代理模式中,代理类(MapperProxy)中才真正的完成了方法调用的逻辑。
MapperProxy的代码如下:

public class MapperProxy<T> implements InvocationHandler, Serializable {
        // 实现了InvocationHandler
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //代理以后,所有Mapper的方法调用时,都会调用这个invoke方法

            if (Object.class.equals(method.getDeclaringClass())) {
                try {
                    return method.invoke(this, args); 
                } catch (Throwable t) {
                    throw ExceptionUtil.unwrapThrowable(t);
                }
            }
            // 使用了缓存
            final MapperMethod mapperMethod = cachedMapperMethod(method); 
            //执行CURD
            return mapperMethod.execute(sqlSession, args); 
        }
    }

再往下一层,就是执行JDBC那一套了,获取链接,执行,得到ResultSet,解析ResultSet映射成JavaBean。

3、总结

Mapper接口是如何产生动态代理对象的,Maper接口方法最终是如何执行的。总结起来主要就是这几个点:

  • Mapper 接口在初始SqlSessionFactory 注册的。
  • Mapper 接口注册在了名为 MapperRegistry 类的 HashMap中, key = Mapper class对象; value = 创建当前Mapper的工厂。
  • Mapper 注册之后,可以从SqlSession中get
  • SqlSession.getMapper 运用了 JDK动态代理,产生了目标Mapper接口的代理对象。
  • 动态代理的 代理类是 MapperProxy ,这里边最终完成了增删改查方法的调用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值