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. Sentry 监控 - Discover 事件大数据查询分析引擎

    系列 1 分钟快速使用 Docker 上手最新版 Sentry-CLI - 创建版本 快速使用 Docker 上手 Sentry-CLI - 30 秒上手 Source Maps Sentry For ...

  2. JavaScript深拷贝实现方式

    1.递归 function deepCope (obj) { // 要拷贝的数据为引用类型属性(数组或对象) if (obj && typeof obj === 'object') { ...

  3. Git - 命令行 常用

    一.合并其他分支的commit(A分支中的commit合并至B分支) 切换到A分支,查询commit历史命令行 : $ git log 复制要合并的commit id (如:663802dfb121e ...

  4. AES加密基本原理图解

    AES加密 Fright-Moch整理 AES简介 高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的).对 ...

  5. 这两个基础seo插件,wordpress网站必装

    WordPress对搜索引擎非常友好,这一点很多人都知道.不过我们在制作完成WordPress主题后,还可以在原来的良好基础上,添加两个队seo非常有利的WordPress插件. 第一个插件:Baid ...

  6. 【深度学习】线性回归(Linear Regression)——原理、均方损失、小批量随机梯度下降

    1. 线性回归 回归(regression)问题指一类为一个或多个自变量与因变量之间关系建模的方法,通常用来表示输入和输出之间的关系. 机器学习领域中多数问题都与预测相关,当我们想预测一个数值时,就会 ...

  7. keeplived高可用配置

    前提:关闭防火墙,关闭selinux 1.主备配置 主 vim keeplived-lb01.confglobal_defs { router_id LVS_01 } vrrp_instance VI ...

  8. Appium iOS 原理

    一.iOS Appium 原理 1.1 iOS 9.3 系统之前自动化测试 1.1.1 Native 自动化 这是 iOS 9.3 系统之前自动化测试的架构模式.通过 Android Appium 原 ...

  9. 2020.10.16--vj个人赛补题

    D - Drinks Choosing Old timers of Summer Informatics School can remember previous camps in which eac ...

  10. 内网渗透DC-4靶场通关

    个人博客:点我 DC系列共9个靶场,本次来试玩一下DC-4,只有一个flag,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题.靶场推荐使用 ...