[TOC]

1.回顾Mybatis执行sql的流程

在之前的代码中咱们的运行过程再梳理一下,首先咱们执行Test,调用dao接口办法

接口的定义:

调用接口的实现类办法:

最初才是调用真正的sql:

下面的代码是在接口实现类外面本人去执行id,查找并执行mapper文件外面的sql,那么咱们想是不是能够缩小一步呢?

如果咱们不必本人实现接口,只须要将接口的名字和mapper文件的namespace对应起来,将接口外面的办法名与sql语句标签的id对应起来是不是就能够了呢?

事实上,mybatis提供了这样的做法,这就是mapper动静代理。

2.mapper动静代理怎么写?

首先主配置文件(Mybatis.xml),在外面配置数据库连贯信息,注册须要扫描的mapper文件:

定义数据库查问的接口,外面每一个接口的名字很重要,须要和mapper外面每一条sql对应起来:

定义mapper文件(namespace是接口的全限定类名):

那咱们在应用的时候,须要应用sqlSession.getMapper()办法,外面传入的是接口,意思是通过接口的全限定名,也就是后面在mapper.xml文件外面配置的命名空间nameSpace,这样一来,就是获取到了代理类,将daomapper.xml文件关联起来了,而每条sqlid与咱们的接口办法名字对应起来)

咱们在后面还写到过一个selectStudentMap()办法,然而外面调用的是和SelectList()一样的sql,在接口的实现类外面咱们本人解决了一下,然而当初应用主动实现的话,底层只会调用SelectOne()或者SelectList()办法,所以这个办法会报错,如果承受类型是list,那么框架会主动应用selectList()办法,否则就会抉择selectOne()这个办法。

在这里咱们应用的是返回的是map,所以主动抉择返回selectOne()办法,那么就会报错。如果咱们须要应用主动返回map的话,能够本人定一个map,或者返回list之后再解决,这个知识点前面再介绍,有趣味能够拜访:mybatis的mapper返回map后果集

3.mapper动静代理怎么做的?

打一个断点在sqlSession.getMapper()办法上:

咱们能够看到执行上面的接口办法(接口SqlSession的办法)

<T> T getMapper(Class<T> var1);

这是一个接口,咱们能够看到实现接口的有两个类,一个是DefaultSqlSession,一个是SqlSessionManager,咱们须要看的是DefaultSqlSession上面的接口:

 public <T> T getMapper(Class<T> type) {    return this.configuration.getMapper(type, this);  }

咱们晓得,在创立sqlsession的时候,confiiguration这个配置对象曾经创立实现。跟进去,这是应用mapper注册器对象的getMapper()办法,将以后的sqlSession对象传递进去:

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {    return mapperRegistry.getMapper(type, sqlSession);  }

咱们跟进去源码,能够发现外面应用knownMappers.get(type)来获取mapper代理工厂,这个konwnMappers是一个hashMap,这个hashMap外面曾经初始化了mapperProxyFactory对象了,获取到工厂对象之后,再去应用sqlSession实例化:

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);    if (mapperProxyFactory == null) {      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");    }    try {      return mapperProxyFactory.newInstance(sqlSession);    } catch (Exception e) {      throw new BindingException("Error getting mapper instance. Cause: " + e, e);    }  }

实例化的时候,应用了mapper动静代理:

public T newInstance(SqlSession sqlSession) {    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);    return newInstance(mapperProxy);  }protected T newInstance(MapperProxy<T> mapperProxy) {    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);  }

从上面的debug后果中咱们能够看到,这是动静代理的后果,咱们看到的是dao,然而动静代理对这个dao做了加强,实则是一个mapperProxy

【作者简介】
秦怀,公众号【秦怀杂货店】作者,技术之路不在一时,山高水长,纵使迟缓,驰而不息。这个世界心愿所有都很快,更快,然而我心愿本人能走好每一步,写好每一篇文章,期待和你们一起交换。

此文章仅代表本人(本菜鸟)学习积攒记录,或者学习笔记,如有侵权,请分割作者核实删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有谬误之处,还望指出,感激不尽~