Mybatis接口Mapper内的方法为啥不能重载吗?
动态代理的功能:通过拦截器方法回调,对目标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);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (Object.class.equals(method.getDeclaringClass())) {
try {
// 诸如hashCode()、toString()、equals()等方法,将target指向当前对象this
return 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;
}
@Override
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);
}
// ...
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)。
Mybatis接口Mapper内的方法为啥不能重载吗?的更多相关文章
- Mybatis的Mapper中的方法为什么不能重载?
目录 前言 环境配置 错误示范 为什么不能重载? 如何找到XML中对应的SQL? 总结 前言 在初入门Mybatis的时候可能都犯过一个错误,那就是在写Mapper接口的时候都重载过其中的方法,但是运 ...
- Mybatis的mapper代理开发方法
一.开发规范 1.映射文件中的namespase等于mapper接口类路径 2.statement的id与mapper中的方法名一致 3.让mapper的接口方法输入参数类型与statement中的p ...
- Mybatis的Mapper接口方法不能重载
今天给项目的数据字典查询添加通用方法,发现里边已经有了一个查询所有数据字典的方法 List<Dict> selectDictList(); 但我想设置的方法是根据数据字典的code查询出所 ...
- mybatis如何通过接口查找对应的mapper.xml及方法执行详解
转:http://www.jb51.net/article/116402.htm 本文主要介绍的是关于mybatis通过接口查找对应mapper.xml及方法执行的相关内容,下面话不多说,来看看详细的 ...
- Mybatis的mapper接口接受的参数类型
最近项目用到了Mybatis,学一下记下来. Mybatis的Mapper文件中的select.insert.update.delete元素中有一个parameterType属性,用于对应的mappe ...
- Mybatis的mapper代理开发dao方法
看完了之前的mybatis原始的dao开发方法是不是觉得有点笨重,甚至说没有发挥mybatis 作为一个框架的优势.总结了一下,原始的dao方法有以下几点不足之处 dao接口实现方法中存在大量的模板方 ...
- mybatis的mapper接口代理使用的三个规范
1.什么是mapper代理接口方式? MyBatis之mapper代理方式.mapper代理使用的是JDK的动态代理策略 2.使用mapper代理方式有什么好处 使用这种方式可以不用写接口的实现类,免 ...
- mybatis由浅入深day01_5.3 Mapper动态代理方法
5.3 Mapper动态代理方法(程序员只需要写mapper接口(相当于dao接口)) 5.3.1 实现原理(mapper代理开发规范) 程序员还需要编写mapper.xml映射文件 程序员编写map ...
- Mybatis框架 使用接口Mapper实现数据库的crud操作
Mybatis的Mapper接口方式实现简单crud操作: 1.创建实体类 与数据库对应 我的实体类是<Student> package com.hxzy.mybatis.pojo; ...
随机推荐
- javaWeb项目之图书管理系统(附视频讲解)
视频播放地址:javaWeb图书系统 本系统为"Swing项目之图书管理系统"(此源码已共享)的Web版,网页框架用采用EasyUI 数据库为MysqL,写Web项目摒弃了火狐浏览 ...
- linux驱动之定时器的介绍和内核时间的学习
本文章摘自下面的网友: http://blog.sina.com.cn/s/blog_6e5b342e0100m87d.html 一.内核中如何记录时间 任何程序都需要时间控制,其主要目的是: 测量时 ...
- Netbox 开源 IPAM 管理工具搭建详细流程
原文链接:Netbox 开源 IPAM 管理工具搭建详细流程 参考资料:https://netbox.readthedocs.io/en/stable/ PostgreSQL数据库安装 1.yum 下 ...
- arp_ignore与arp_announce
arp_ignore:定义接收到ARP请求时的响应级别0:只要本地设置的有相应的地址,就给予响应.(默认)1:仅回应目标IP地址是本地的入网地址的arp请求.2:仅回应目标IP地址是本地的入网地址,而 ...
- .NET 设计模式 思维导图
关于.NET 设计模式 思维导图 背景说明 以前都在匆匆忙忙写代码,在无穷无尽的需求中间左冲右突,最近终于有一些闲暇的时间,来总结和思考编程中的一些核心思想,磨刀不误砍柴的功夫,期望通过总结和学习,能 ...
- 牛客网PAT练兵场-人口普查
题目地址:https://www.nowcoder.com/pat/6/problem/4054 题解:结构体排序即可 /** * Copyright(c) * All rights reserved ...
- 基于 GitBook 搭建个人博客
目录 基于 GitBook 搭建个人博客 1.为什么要写博客? 2.为什么选择使用 GitBook 来搭建? 3.搭建方式 3.1 GitBook 线上直接搭建 3.2 由基于Node.js的命令工具 ...
- GitBook 常用插件
目录 必看说明 插件说明 page-treeview 目录 code 代码 pageview-count 阅读量计数 popup 图片点击查看 tbfed-pagefooter 页面添加页脚(简单版) ...
- new操作符创建对象的四个步骤
new操作符创建对象可以分为以下四个步骤: 创建一个空对象 将所创建对象的__proto__属性值设为构造函数的prototype的属性值 执行构造函数中的代码,构造函数中的this指向该对象 返回对 ...
- Python 批量下载BiliBili视频 打包成软件
文章目录 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人,我给大家 ...