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; ...
随机推荐
- JavaScript设计模式之命令模式【命令解耦】
在讲解命令模式之前我们先来了解一个生活中的命令模式场景: 场景1: 医院看病抓药: 当你因为肾虚到医院看医生,医生一番操作之后得出结论:要吃个疗程[夏桑菊].[小柴胡](药名纯属虚构,真的肾虚就找医生 ...
- 12c RAC 用Rman 恢复到异机单实例
准备工作 原服务器软件部署:Redhat 6.6 + Oracle 12.2.0.1 rac Oracle12c单实例安装 1.创建恢复服务器,设置大于原库数据大小的磁盘容量.设置相同的服务器主机名参 ...
- Go interface 操作示例
原文链接:Go interface操作示例 特点: 1. interface 是一种类型 interface 是一种具有一组方法的类型,这些方法定义了 interface 的行为.go 允许不带任何方 ...
- Linux用户和组密令大全
本文总结了Linux添加或者删除用户和用户组时常用的一些命令和参数. 1.建用户: adduser phpq passwd phpq ...
- Linux下执行SQL文件
最近在使用MySQL数据库时,想要执行一些sql文件,就想到了source命令. source介绍:source命令也称为“点命令”,也就是一个点符号(.),是bash的内部命令. 功能:使Shell ...
- Training spiking neural networks for reinforcement learning
郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! 原文链接:https://arxiv.org/pdf/2005.05941.pdf Contents: Abstract Introduc ...
- linux系统学习
一.linux系统如何配置环境变量 1.在Windows 系统下,很多软件安装都需要配置环境变量,比如 安装 jdk ,如果不配置环境变量,在非软件安装的目录下运行javac 命令,将会报告找不到文件 ...
- Java抽象类简述
Java 抽象类 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类. 抽象类除了不 ...
- C# 接口的Get、Post、WebService请求方法一览,值得收藏
C# 接口的Get.Post.WebService请求方法一览,值得收藏 public static class HttpHelper { const string DEFAULT_USER_AGEN ...
- 重温Java Web的技术细节
目录 一.背景 二.请求与响应 2.1.Http请求 2.2.Http响应 三.ServletConfig 3.1 测试ServletConfig参数 四.ServletContext 4.1 测试S ...