Mybatis只有接口没有实现类的原理

Posted bruce128

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis只有接口没有实现类的原理相关的知识,希望对你有一定的参考价值。

一、问题背景

mybaits相对于Ibatis的一大区别就是,不用自己写接口实现类。Ibatis的实现类十几年来做着重复的工作,拼接statementId,然后执行sql。十分没有营养的代码。mybaits干脆不用手工写实现类了,框架帮我们完成了这件事情。

二、实现原理

mybatis使用了动态代理技术生成实现类。动态代理的具体手段有两种:jdk自带和cglib。

动态代理技术对比jdk自带cglib
是否需要声明接口需要不需要
是否需要实现类不需要需要

虽然都是生成字节码新类,但是cglib的字节码新类需要继承实现类。对于mybatis只有接口的场景,当然选择jdk自带的动态代理。

三、源码分析

mybatis动态代理两个核心类

org.apache.ibatis.binding.MapperProxy
org.apache.ibatis.binding.MapperProxyFactory
  • MapperProxy作用
public class MapperProxy<T> implements InvocationHandler, Serializable 
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
    ... ...
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  

这个类实现了代理拦截器方法,也就意味着,新生成的所有代理类的方法都会走这个invoke方法里的逻辑。invoke方法最后一行做了什么呢?

  1. 拼接statementID
  2. 执行sql
  3. 返回结果

这不正是之前写Ibatis接口实现类的时候,天天重复写的代码吗?

  • MapperProxyFactory 作用
public class MapperProxyFactory<T> 

  @SuppressWarnings("unchecked")
  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, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  



MapperProxyFactory是代理工厂类,根据传入的DAO的接口,生成对应实现的动态代理类。每个接口一个动态代理实现类,于是乎,再也不用写Ibatis的那些冗余的代码。

四、结语

mybatis设计的很巧妙,把在ibatis中重复的逻辑用一个动态代理的拦截器进行去重。很高级的duplicate code重构技巧。一个好的架构,可以节省开发同学的时间。

以上是关于Mybatis只有接口没有实现类的原理的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis为什么只有mapper接口没有实现类

MyBatis原理总结(手写实现类)

MyBatis接口的简单实现原理

Mybatis源码分析之Cache二级缓存原理

MyBatis缓存详解

MyBatis是如何为Dao接口创建实现类的