当前位置: 移动技术网 > IT编程>开发语言>Java > mybatis源码探究(-)MapperProxyFactory&MapperProxy

mybatis源码探究(-)MapperProxyFactory&MapperProxy

2018年08月23日  | 移动技术网IT编程  | 我要评论

在mybatis中mapperproxyfactory,mapperproxy,mappermethod是三个很重要的类。

弄懂了这3个类你就大概清楚mapper接口与sql的映射,

为什么是接口,没有实例类也可以完成注入或者调用

其中mappermethod可以参考:mappermethod源码分析传送门

在调用mybatis的addmapper的时候如果你跟踪源码就会最终跟到mapperregistry的addmapper中有如下的语句:

knownmappers.put(type, new mapperproxyfactory<t>(type));

 

type就是mapper接口。下面我们来看一下mapperproxyfactory的源码。

mapperproxyfactory

public class mapperproxyfactory<t> {

  private final class<t> mapperinterface;
  private map<method, mappermethod> methodcache = new concurrenthashmap<method, mappermethod>();

  public mapperproxyfactory(class<t> mapperinterface) {
    this.mapperinterface = mapperinterface;
  }

  public class<t> getmapperinterface() {
    return mapperinterface;
  }

  public map<method, mappermethod> getmethodcache() {
    return methodcache;
  }

  @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一看名字我们就知道肯定是一个工厂类,就是为了生成mapperproxy。其实mapperproxyfactory也非常简单。首先看2个成员mapperinterface就是mapper接口,methodcache就是对mapper接口中的方法和方法的封装类(mappermethod)的映射。mappermethod处理的事情主要就是:处理mapper接口中方法的注解,参数,和返回值。如果想了解更多的细节可以参考mappermethod源码分析传送门

然后就是2个newinstance,看名字就知道是工厂方法,一个是protected,一个是public,所以首先看public方法。发现有一个参数sqlsession,sqlsession处理的其实就是执行一次sql的过程。其实public的newinstance就是new了一个mapperproxy,关于mapperproxy可以先看一下后面的mapperproxy。然后调用了protected的newinstance。

接着我们看protected的newinstance。protected简单明了,就是使用java proxy的工厂方法生成一个了mapper接口的代理类。我想都关系mybatis源码了应该对java的proxy动态代理方式应该非常熟悉了。如果不熟悉可以参考一下我之前写的一篇关于java动态代理的java动态代理细探

我们指定mapperproxy实现了invocationhandler,所以调用mapper接口中的方法走的是mapperproxy的invoke。而mapperproxy的invoke是把method包装成了mappermethod,mappermethod处理了mapper接口方法与xml映射的关系。是不是串联起来了。

mapperproxy

public class mapperproxy<t> implements invocationhandler, serializable {

  private static final long serialversionuid = -6424540398559729838l;
  private final sqlsession sqlsession;
  private final class<t> mapperinterface;
  private final map<method, mappermethod> methodcache;

  public mapperproxy(sqlsession sqlsession, class<t> mapperinterface, map<method, mappermethod> methodcache) {
    this.sqlsession = sqlsession;
    this.mapperinterface = mapperinterface;
    this.methodcache = methodcache;
  }

  public object invoke(object proxy, method method, object[] args) throws throwable {
    if (object.class.equals(method.getdeclaringclass())) {
      try {
        return method.invoke(this, args);
      } catch (throwable t) {
        throw exceptionutil.unwrapthrowable(t);
      }
    }
    final mappermethod mappermethod = cachedmappermethod(method);
    return mappermethod.execute(sqlsession, args);
  }

  private mappermethod cachedmappermethod(method method) {
    mappermethod mappermethod = methodcache.get(method);
    if (mappermethod == null) {
      mappermethod = new mappermethod(mapperinterface, method, sqlsession.getconfiguration());
      methodcache.put(method, mappermethod);
    }
    return mappermethod;
  }

}

我们看mapperproxy实现了invocationhandler接口,不用仔细想,基本上是因为java动态代理。

既然实现了invocationhandler接口那么当然要先看一下invoke方法了。首先检查了如果是object中方法就直接调用方法本身。

如果不是就把方法method包装成mappermethod,我们前面已经提到了mappermethod主要就是处理方法的注解,参数,返回值,参数与sql语句中的参数的对应关系。再次打一波广告,如果像了解更多mappermethod的细节可以参考mappermethod源码分析传送门

因为把method处理为mappermethod还是一个比较重的操作,所以这里做了缓存处理。

小结

总结一下,我们公共mybatis添加的mapper的操作实际上添加的是mapperproxyfactory,这个是mapperproxy的工厂类,但是mapperproxyfactory生产的也不是mapperproxy,而是mapper的proxy代理。使用的invocationhandler是mapperproxy,mapperproxy的invoke方法实际上是把mapper接口方法包装为了mappermethod,并执行的mappermethod的execute方法。mappermethod处理的逻辑是mapper方法与xml中的sql的一些映射关系。例如@mapkey等注解的处理,一些如rowbounds特殊参数的处理以及一些其他关于mapper方法与sql映射的处理。执行sql的逻辑其实是委托给了sqlsession相关的逻辑。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网