Mybatis的Mapper接口UserMapper

 1 package com.safin.Mapper;
2
3 import com.safin.Pojo.User;
4
5 import java.util.List;
6
7 public interface UserMapper {
8 int insertUser(User user);
9 User getUser(Long id);
10 List<User> findUser(String userName);
11 }

我使用的jdk版本是12的,在java.lang.reflect包下的ProxyGenerator是生成代理类的工具,这是用来生成运行时代理类($proxy为前缀)。注意其中一个属性,这是用来保存那些构建的代理类的开关saveGeneratedFiles,其默认赋值是false,当saveGeneratedFiles的值为true时,那些运行时生成的代理类将会以.class文件保存下来。

1 /** debugging flag for saving generated class files */
2 private static final boolean saveGeneratedFiles =
3 java.security.AccessController.doPrivileged(
4 new GetBooleanAction(
5 "jdk.proxy.ProxyGenerator.saveGeneratedFiles")).booleanValue();

在测试主函数开始第一句先添加如下代码,把saveGeneratedFiles的开关打开。jdk12中的"jdk.proxy.ProxyGenerator.saveGeneratedFiles"这个值与jdk8中的稍微不同,在jdk8的这个值是"sun.misc.ProxyGenerator.saveGeneratedFiles"。说起misc,他的全称应该是minimal instruction set computer,最小指令集计算机是一种处理器体系结构,具有非常少量的基本操作和相应的操作码。

还有jdk8与jdk12的Proxy的实现发生了很大的变化,以后有时间再去研究研究。

1 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true");

测试的Main函数如下:

 1 public static void main(String[] args) throws IOException {
2 SqlSession sqlSession = null;
3 System.getProperties().put("jdk.proxy.ProxyGenerator.saveGeneratedFiles", "true"); // 打开保存生成的代理类
4
5 try {
6 sqlSession = SqlSessionFactoryUtil.openSqlSession();
7 UserMapper userMapper = (UserMapper)sqlSession.getMapper(UserMapper.class);
8 User user = null;
9 user = userMapper.getUser(30L);
10 sqlSession.commit();
11 } catch (Exception var9) {
12 System.err.println(var9.getMessage());
13 sqlSession.rollback();
14 } finally {
15 if (sqlSession != null) {
16 sqlSession.close();
17 }
18
19 }
20
21 }

运行后保存了许多代理类,找出与Mapper有关的的代理类$proxy,代理类经过IDEA的反编译后,代码如下:

  1 //
2 // Source code recreated from a .class file by IntelliJ IDEA
3 // (powered by Fernflower decompiler)
4 //
5
6 package com.sun.proxy;
7
8 import com.safin.Mapper.UserMapper;
9 import com.safin.Pojo.User;
10 import java.lang.reflect.InvocationHandler;
11 import java.lang.reflect.Method;
12 import java.lang.reflect.Proxy;
13 import java.lang.reflect.UndeclaredThrowableException;
14 import java.util.List;
15
16 public final class $Proxy19 extends Proxy implements UserMapper {
17 private static Method m1;
18 private static Method m3;
19 private static Method m4;
20 private static Method m5;
21 private static Method m2;
22 private static Method m0;
23   
24 public $Proxy19(InvocationHandler var1) throws {
25 super(var1);   // 传入构造方法的参数是实现了InvocationHandler接口的MapperProxy
26 }
27
28 public final boolean equals(Object var1) throws {
29 try {
30 return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); // 从InvocationHandler的invoke方法
31 } catch (RuntimeException | Error var3) {
32 throw var3;
33 } catch (Throwable var4) {
34 throw new UndeclaredThrowableException(var4);
35 }
36 }
37
38 public final User getUser(Long var1) throws {
39 try {
40 return (User)super.h.invoke(this, m3, new Object[]{var1});
41 } catch (RuntimeException | Error var3) {
42 throw var3;
43 } catch (Throwable var4) {
44 throw new UndeclaredThrowableException(var4);
45 }
46 }
47
48 public final int insertUser(User var1) throws {
49 try {
50 return (Integer)super.h.invoke(this, m4, new Object[]{var1});
51 } catch (RuntimeException | Error var3) {
52 throw var3;
53 } catch (Throwable var4) {
54 throw new UndeclaredThrowableException(var4);
55 }
56 }
57
58 public final List findUser(String var1) throws {
59 try {
60 return (List)super.h.invoke(this, m5, new Object[]{var1});
61 } catch (RuntimeException | Error var3) {
62 throw var3;
63 } catch (Throwable var4) {
64 throw new UndeclaredThrowableException(var4);
65 }
66 }
67
68 public final String toString() throws {
69 try {
70 return (String)super.h.invoke(this, m2, (Object[])null);
71 } catch (RuntimeException | Error var2) {
72 throw var2;
73 } catch (Throwable var3) {
74 throw new UndeclaredThrowableException(var3);
75 }
76 }
77
78 public final int hashCode() throws {
79 try {
80 return (Integer)super.h.invoke(this, m0, (Object[])null);
81 } catch (RuntimeException | Error var2) {
82 throw var2;
83 } catch (Throwable var3) {
84 throw new UndeclaredThrowableException(var3);
85 }
86 }
87
88 static { // 拿到了反射API的Method
89 try {
90 m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
91 m3 = Class.forName("com.safin.Mapper.UserMapper").getMethod("getUser", Class.forName("java.lang.Long"));
92 m4 = Class.forName("com.safin.Mapper.UserMapper").getMethod("insertUser", Class.forName("com.safin.Pojo.User"));
93 m5 = Class.forName("com.safin.Mapper.UserMapper").getMethod("findUser", Class.forName("java.lang.String"));
94 m2 = Class.forName("java.lang.Object").getMethod("toString");
95 m0 = Class.forName("java.lang.Object").getMethod("hashCode");
96 } catch (NoSuchMethodException var2) {
97 throw new NoSuchMethodError(var2.getMessage());
98 } catch (ClassNotFoundException var3) {
99 throw new NoClassDefFoundError(var3.getMessage());
100 }
101 }
102 }

可以看见生成的代理类 $Proxy19 继承了 Proxy 类,实现了Mybatis的 UserMapper 接口,调用InvocationHandler的invoke方法来利用MapperMethod来对sqlSession的操作。

如果上面的main方法配置行不通,还有一种是通过配置JVM参数 -Dsun.misc.ProxyGenerator.saveGeneratedFiles=true 来把JDK生成的代理类持久化到本地。

探索Mybatis之JDK动态代理:探究Proxy.newProxyInstance()生成的代理类解析的更多相关文章

  1. 设计模式 - 代理模式(proxy pattern) 未使用代理模式 具体解释

    代理模式(proxy pattern) 未使用代理模式 详细解释 本文地址: http://blog.csdn.net/caroline_wendy 部分代码參考: http://blog.csdn. ...

  2. Java-马士兵设计模式学习笔记-代理模式-动态代理 调用Proxy.newProxyInstance()

    一.概述 1.目标:不自己写代理类,利用Proxy.newProxyInstance()动态生成 2.用到的知识点: (1)//编译源码,生成class,注意编译环境要换成jdk才有compiler, ...

  3. Java JDK动态代理解析

    动态代理虽不常自己实现,但在Spring或MyBatis中都有重要应用.动态代理的意义在于生成一个占位(又称代理对象),来代理真实对象,从而控制真实对象的访问.Spring常JDK和CGLIB动态代理 ...

  4. jdk动态代理(转)

    一旦这样绑定后,那么在进入代理对象方法调用的时候就会到HelloServiceProxy的invoke方法上,invoke方法有三个参数:第一个proxy是代理对象,第二个是当前调用那个方法,第三个是 ...

  5. JDK动态代理为什么必须要基于接口?

    原创:微信公众号 码农参上,欢迎分享,转载请保留出处. 前几天的时候,交流群里的小伙伴抛出了一个问题,为什么JDK的动态代理一定要基于接口实现呢? 好的安排,其实要想弄懂这个问题还是需要一些关于代理和 ...

  6. 基于Spring AOP的JDK动态代理和CGLIB代理

    一.AOP的概念  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的 ...

  7. JDK动态代理的实现及原理

    Proxy.newProxyInstance(classloader,Class,invocationHandler) 调用getProxyClass0(loader, interfaces)生成代理 ...

  8. Java基础-JDK动态代理

    JDK的动态代理依靠接口实现  代理模式 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代 ...

  9. Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理

    Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理 JDK动态代理的实现及原理 作者:二青 邮箱:xtfggef@gmail.com     微博:http://weibo.com/xtfg ...

随机推荐

  1. 法术迸发(Spellburst)

    描述 法术迸发 (EN:Spellburst ) 是一种在<通灵学园>中加入的关键字异能,在玩家打出一张法术牌后触发,只能触发一次. 若随从在法术结算过程中死亡,则不会触发效果 思路 首先 ...

  2. 【第一篇】- Maven 系列教程之Spring Cloud直播商城 b2b2c电子商务技术总结

    Maven 教程 Maven 翻译为"专家"."内行",是 Apache 下的一个纯 Java 开发的开源项目.基于项目对象模型(缩写:POM)概念,Maven ...

  3. Excel表格中单击一个单元格如何将整行整列变色

    视图->阅读模式 开启阅读模式后 就会显示如下情景,是的你点击任意单元格后,显示整行/整列

  4. python 直接插入排序

    # 先将未排序的元素放到九天之上,一个临时变量temp,上到九天之上去观察前面已经排好的序列, # 然后从后向前对比,只要临时变量小于某个位置的值,就将其向前移动一位,就是给比它下标大 # 1的位置处 ...

  5. Android使用Fragment+ViewPager +TabLayout实现顶部标题栏

    参考资料: https://blog.csdn.net/Tobey_r1/article/details/93221486 项目背景是Android开发新闻APP,实现新闻文本的分类,内容的展示,并实 ...

  6. 免费iApp后台-云接口

    免费稳定,UI易懂简洁,功能强大 应用名称:云接口 应用版本:1.5.9 应用大小:3.55 MB 适用平台:Android(安卓) 应用用处:详情请下载软件 软件安全无毒 更新内容: 1.支付宝当面 ...

  7. mysql 复合索引 为什么遵循最左原则

    1,>mysql :多列索引  https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html 1>,B+树: h ...

  8. P3964-[TJOI2013]松鼠聚会【计算几何】

    正题 题目链接:https://www.luogu.com.cn/problem/P3964 题目大意 给出\(n\)个点,求一个点使得它到所有点的切比雪夫距离和最小. \(0\leq n\leq 1 ...

  9. 一篇文章告诉你Python接口自动化测试中读取Text,Excel,Yaml文件的方法

    前言 不管是做Ui自动化和接口自动,代码和数据要分离,会用到Text,Excel,Yaml.今天讲讲如何读取文件数据 Python也可以读取ini文件,传送门 记住一点:测试的数据是不能写死在代码里面 ...

  10. Redis之品鉴之旅(一)

    Redis之品鉴之旅(一) 好知识就如好酒,需要我们坐下来,静静的慢慢的去品鉴.Redis作为主流nosql数据库,在提升性能的方面是不可或缺的.下面就拿好小板凳,我们慢慢的来一一品鉴. 1)redi ...