回答完Mybatis的问题,面试官让我回去等通知。我们可以直接调用它的方法吗?关于这个问题,之前采访过一些人,很多人是这样回答的:1.我领导让我们用Mybatis,大家都是这样用的(没想到,反正我是这样用的).2.虽然不知道是怎么实现的,但我想一定是……(这里省略了一些乱猜),但是不对,难道是……(有些半懂半懂的又省略了).3.使用动态代理实现(那么下面就不再赘述)。以上三个答案,前两个不用说了。但是对于第三个回答,有必要问一下:动态代理的实现方式有哪些?Mybatis用的是哪一个?如果你能回答这个问题,你会继续问:UserMapper.java中大方法可以重载吗?如果你能回答以上问题,这篇文章就没必要看了,它已经不适合你了。问题分析我们先来看一张图。这张图的代码就是我们之前写的demo:为什么一个接口可以绑定一个xml文件?这就是我们今天要聊的话题。可能很多朋友对ibatis并不熟悉。2010年之前没有Mybatis,后来ibatis变成了现在的Mybatis。有兴趣的可以看看Mybatis中的包目录。这个包目录还是ibatis,ibatis的作者现在在腾讯工作,开发英雄联盟LOL。有腾讯的小伙伴可以打听一下,老大就在你身边。离家更近。Mybatis中的Mapper层现在是接口的形式,但是在ibatis时代,必须要有一个实现类。记得2012年用的是ibatis,Dao(Mapper)肯定有实现类。我们来看看在Mybatis中是怎么做的。用例继续使用我们上一节中的代码。在controllerservice实现类打断点,然后使用debug模式启动项目。并且访问:http://localhost:9002/testuserMapper=org.apache.ibatis.binding.MapperProxy@6da21078发现Mybatis为UserMapper.java生成了一个代理对象,从名字就可以看出是一个JDK动态的代理人。关于动态代理,这里推荐一下我之前写的一篇文章:https://gitbook.cn/m/mazi/activity/5d44e35e4fbf44126135c292?sut=c93c00a03b4f11eba07ad99b4dfbdab0&utm_source=chatweixinshare其实差不多回到了ibatis时代,但是在Mybatis中动态代理生成的代理类不是我们自己开发的,是JDK动态代理生成的代理类。下面我们也用JDK动态代理来模拟一个。publicclassMapperProxyimplementsInvocationHandler{@SuppressWarnings("unchecked")publicTnewInstance(Classclz){return(T)Proxy.newProxyInstance(clz.getClassLoader(),newClass[]{clz},this);}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(Object.class.equals(method.getDeclaringClass())){try{//hashCode(),toString(),equals()等方法,点target到当前Objectthisreturnmethod.invoke(this,args);}catch(Throwablet){}}//甩鞭断流returnnewUser((Integer)args[0],"田伟昌",22);}}编写另一个测试类importcom.tian.mybatis.entity.User;importcom.tian.mybatis.mapper.UserMapper;publicclassTestProxy{publicstaticvoidmain(String[]args){MapperProxyproxy=newMapperProxy();UserMappermapper=proxy.newInstance(UserMapper.class);Useruser=mapper.selectById(999);System.out.println(user);System.out.println(mapper.toString());}}输出User{id=999,userName='田伟昌',age=22,gender=null}com.tian.mybatis.proxy.MapperProxy@39a054a5这是Mybatis自动映射器Mapper的底层实现原理。但是在Mybatis中,远没有那么简单,但本质是这样的。下面简单分析下Mybatis中的流程。接口Mapper中的方法是否可以重载?类似如下:publicUsergetUserById(Integerid);publicUsergetUserById(Integerid,Stringname);答:不是因为Mybatis使用了package+Mapper+method的全限定名作为key,去xml里面找唯一的sql去执行。类似于:key=com.tian.mybatis.UserMapper.getUserById,那么重载该方法就会产生矛盾。对于Mapper接口,Mybatis禁止方法重载(overLoad)。MapperMethod类的静态内部类中的SqlCommand中有一个resolveMappedStatement方法。Configuration中有一个属性,就是当项目启动时,会将Mapper.xml中的信息解析到这个属性中,并将我们指定的namespace+method作为key放到Map中。后面我们会调用一个Mapper接口的动态类的方法,使用的时候去map里面获取。protectedfinalMapmappedStatements是使用类的全路径名。该方法作为键存储在Map中。总结一下常用的动态代理方式:JDK动态代理和CGlib动态代理。Mybatis使用JDK动态代理+反射+xml解决接口绑定,创建可以为我们调用的代理对象。我们的Mapper中的方法绝不能重载。前端小智本文转载自微信公众号《Java后端技术全栈》,可通过以下二维码关注。转载本文请联系Java后端技术全栈公众号。