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. Windows下安装程序时提示未安装Microsoft Net FrameWork 2.0

    问题描述 安装程序时碰到如下: 现在基本都是用win7.win10系统,缺少环境大多数都是因为系统没有启用. 解决方法 控制面板 - 程序 - 启用或关闭Windows功能 - 把第一项'NET Fr ...

  2. python-引用/模块

    导入文件,先从当前目录下找,找不到从环境变量中找 1.导入模块,实质是把制定的py文件执行一遍. 自己写的模块:要导入的文件在当前目录下的:form 文件夹.py文件名 import 函数名 标准模块 ...

  3. python win32com 处理excle 写一个公共的类

    利用win32com处理excle,这样可以不管文件是老的xls还是新的xlsx格式,非常方便. 类的源码如下: import win32com.client as win32 class easyE ...

  4. 【Python机器学习实战】决策树与集成学习(七)——集成学习(5)XGBoost实例及调参

    上一节对XGBoost算法的原理和过程进行了描述,XGBoost在算法优化方面主要在原损失函数中加入了正则项,同时将损失函数的二阶泰勒展开近似展开代替残差(事实上在GBDT中叶子结点的最优值求解也是使 ...

  5. scrum项目冲刺_day05总结

    摘要:今日完成任务. 1.语音识别完成 2.搜索功能实现了从数据库中的查询 总任务: 一.appUI页面(已完成) 二.首页功能: 1.图像识别功能(已完成) 2.语音识别功能(已完成) 3.垃圾搜索 ...

  6. KMP算法解决字符串匹配问题

    要解决的问题 假设字符串str长度为N,字符串match长度为M,M <= N, 想确定str中是否有某个子串是等于match的.返回和match匹配的字符串的首字母在str的位置,如果不匹配, ...

  7. Java基础系列(3)- HelloWorld详解

    HelloWorld 1.新建一个java文件 文件后缀名为.java Hello.java [注意点]系统可能没有显示文件后缀名,我们需要手动打开 2.编写代码 public class Hello ...

  8. jmeter之命令行执行jmx脚本

    使用界面执行不稳定,且保存报告非常麻烦 https://www.jb51.net/article/191367.htm 作者:Anthony_tester 来源:CSDN 原文:https://blo ...

  9. 鸿蒙内核源码分析(管道文件篇) | 如何降低数据流动成本 | 百篇博客分析OpenHarmony源码 | v70.01

    百篇博客系列篇.本篇为: v70.xx 鸿蒙内核源码分析(管道文件篇) | 如何降低数据流动成本 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么说一 ...

  10. NWERC2020J-Joint Excavation【构造,贪心】

    正题 题目链接:https://codeforces.com/gym/103049/problem/J 题目大意 \(n\)个点\(m\)条边的一张无向图,选出一条路径后去掉路径上的点,然后将剩下的点 ...