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重构技巧。一个好的架构,可以节省开发同学的时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值