点击上方 好好学java ,选择 星标 公众号重磅资讯、干货,第一时间送达
今日推荐:Nginx 为什么快到根本停不下来?个人原创100W+访问量博客:点击前往,查看更多作者:祖大俊来源:my.oschina.net/zudajun/blog/666223

动态代理的功能:通过拦截器方法回调,对目标target方法进行增强。

言外之意就是为了增强目标target方法。上面这句话没错,但也不要认为它就是真理,殊不知,动态代理还有投鞭断流的霸权,连目标target都不要的科幻模式。

注:本文默认认为,读者对动态代理的原理是理解的,如果不明白target的含义,难以看懂本篇文章,建议先理解动态代理。

1. 自定义JDK动态代理之投鞭断流实现自动映射器Mapper

首先定义一个pojo。

public class User {private Integer id;private String name;private int age;public User(Integer id, String name, int age) {this.id = id;this.name = name;this.age = age;}// getter setter
}

再定义一个接口UserMapper.java。

public interface UserMapper {public User getUserById(Integer id);
}

接下来我们看看如何使用动态代理之投鞭断流,实现实例化接口并调用接口方法返回数据的。

自定义一个InvocationHandler。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class MapperProxy implements InvocationHandler {@SuppressWarnings("unchecked")public <T> T newInstance(Class<T> clz) {return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] { clz }, this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {try {// 诸如hashCode()、toString()、equals()等方法,将target指向当前对象thisreturn method.invoke(this, args);} catch (Throwable t) {}}// 投鞭断流return new User((Integer) args[0], "zhangsan", 18);}
}

上面代码中的target,在执行Object.java内的方法时,target被指向了this,target已经变成了傀儡、象征、占位符。在投鞭断流式的拦截时,已经没有了target。

写一个测试代码:


public static void main(String[] args) {MapperProxy proxy = new MapperProxy();UserMapper mapper = proxy.newInstance(UserMapper.class);User user = mapper.getUserById(1001);System.out.println("ID:" + user.getId());System.out.println("Name:" + user.getName());System.out.println("Age:" + user.getAge());System.out.println(mapper.toString());
}

output:

ID:1001
Name:zhangsan
Age:18
x.y.MapperProxy@6bc7c054

这便是Mybatis自动映射器Mapper的底层实现原理。

可能有读者不禁要问:你怎么把代码写的像初学者写的一样?没有结构,且缺乏美感。

必须声明,作为一名经验老道的高手,能把程序写的像初学者写的一样,那必定是高手中的高手。这样可以让初学者感觉到亲切,舒服,符合自己的Style,让他们或她们,感觉到大牛写的代码也不过如此,自己甚至写的比这些大牛写的还要好,从此自信满满,热情高涨,认为与大牛之间的差距,仅剩下三分钟。

2. Mybatis自动映射器Mapper的源码分析

首先编写一个测试类:

public static void main(String[] args) {SqlSession sqlSession = MybatisSqlSessionFactory.openSession();try {StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);List<Student> students = studentMapper.findAllStudents();for (Student student : students) {System.out.println(student);}} finally {sqlSession.close();}}

Mapper长这个样子:


public interface StudentMapper {List<Student> findAllStudents();Student findStudentById(Integer id);void insertStudent(Student student);
}

org.apache.ibatis.binding.MapperProxy.java部分源码。

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;}@Overridepublic 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);}// ...

org.apache.ibatis.binding.MapperProxyFactory.java部分源码。

public class MapperProxyFactory<T> {private final Class<T> mapperInterface;@SuppressWarnings("unchecked")protected T newInstance(MapperProxy<T> mapperProxy) {return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}

这便是Mybatis使用动态代理之投鞭断流。

3. 接口Mapper内的方法能重载(overLoad)吗?(重要)

类似下面:

public User getUserById(Integer id);
public User getUserById(Integer id, String name);

Answer:不能。

原因:在投鞭断流时,Mybatis使用package+Mapper+method全限名作为key,去xml内寻找唯一sql来执行的。类似:key=x.y.UserMapper.getUserById,那么,重载方法时将导致矛盾。对于Mapper接口,Mybatis禁止方法重载(overLoad)。

最后,再附上我历时三个月总结的 Java 面试 + Java 后端技术学习指南,笔者这几年及春招的总结,github 1.4k star,拿去不谢!下载方式1. 首先扫描下方二维码
2. 后台回复「Java面试」即可获取

Mybatis接口Mapper内的方法为啥不能重载吗?相关推荐

  1. Mybatis接口Mapper内的方法为啥不能重载?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:https://my.oschina.net/zud ...

  2. 支付宝二面:Mybatis接口Mapper内的方法为啥不能重载吗?我直接懵逼了...

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:祖大俊来源:my.oschina.net/zudajun/b ...

  3. 支付宝二面:Mybatis 接口 Mapper 内的方法为啥不能重载吗?我直接懵逼了。。。

    动态代理的功能:通过拦截器方法回调,对目标target方法进行增强. 言外之意就是为了增强目标target方法.上面这句话没错,但也不要认为它就是真理,殊不知,动态代理还有投鞭断流的霸权,连目标tar ...

  4. Mybatis的mapper代理开发方法

    一.开发规范 1.映射文件中的namespase等于mapper接口类路径 2.statement的id与mapper中的方法名一致 3.让mapper的接口方法输入参数类型与statement中的p ...

  5. Python-特殊方法(迭代器,生成器,内建方法,运算符重载)

    Python是一门独特的语言,力求简洁,它甚至不像某些语言(如Java)提供接口语法,Python语言采用的是"约定"规则,它提供了大量具有特殊意义的方法,这些方法有些可以直接使用 ...

  6. mybatis接口中的方法重载_MyBatis底层实现原理: 动态代理的运用

    点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 作者:祖大俊 my.oschina.net/zudajun/blog/666223 一日小 ...

  7. Mybatis中mapper接口里方法重载的实现

    看了网上的很多文章,说mapper接口里不能写重载方法,感觉这种说法不对,mapper接口是可以实现重载方法的. 实现方法 例如: package mapper;import pojo.User;im ...

  8. TKmybatis的使用,MyBatis的Mapper接口、Example方法

    文章目录 TKmybatis的使用 TKmybatis的常用注解 Mapper中的方法(dao继承可用) Example方法设置查询条件 TKmybatis的使用 pom.xml导入依赖 <!- ...

  9. mybatis接口中的方法重载_MyBatis的Mapper接口以及Example的实例函数及详解

    一.mapper接口中的方法解析 mapper接口中的函数及方法 方法 功能说明 int countByExample(UserExample example) thorws SQLException ...

最新文章

  1. Java内存模型(Java Memory Model,JMM)
  2. [19/04/23-星期二] GOF23_创建型模式(工厂模式、抽象工厂模式)
  3. 移动端web开发整理
  4. Go语言,在Ubuntu9.10和Windows安装
  5. linux my.cnf基本参数,Linux中MySQL配置文件my.cnf参数说明
  6. 安全云盘项目(四)4.1: 云盘原型系统详细设计
  7. HTML中元素的position属性详解
  8. 关系型数据库(八),数据库其他面试题
  9. 基于机器学习的恶意网站/仿冒网站检测实战
  10. BlackBerry模拟器中文转换
  11. 资源 | 最新版区块链术语表(中英文对照)2019-1.14
  12. 像京东等大厂为什么不通过减薪来代替裁员,降低成本?
  13. 深入理解计算机系统 csapp 家庭作业(第三章完整版)
  14. WESTCAR系列的液力偶合器rotofluid、rotomec、kda
  15. [Maven进阶]多环境配置与应用
  16. python怎么定义int变量_Python 变量类型 | 菜鸟教程
  17. PETS 5 考试经验
  18. 很多智能手表都用6739芯片_天诺智能手表伴童年,AI智能在身边
  19. size_t类型是什么意思?
  20. Android集成腾讯信鸽推送SDK

热门文章

  1. 几种用函数指针方式来访问类成员函数的方法总结
  2. ST17H26 SDK中宏定义注意事项
  3. 测验2: Python基本图形绘制 (第2周)
  4. Zookeeper集群的搭建及遇到的问题
  5. C++(四)——类和对象(下)
  6. java结丹期(13)----javaweb(responserequestservletcontext)
  7. [Java基础]Map集合的遍历
  8. 51. N 皇后(回溯算法)
  9. buu [GXYCTF2019]CheckIn
  10. 【django】模板(templates)