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. js简单化技巧

    1.交换两个变量而没有第三个 let x = 1;let y = 2;[x, y] = [y, x];console.log(x, y); 输出: 2 1 2.将数字转换为字符串 const num  ...

  2. 【Azure API 管理】APIM 配置Validate-JWT策略,验证RS256非对称(公钥/私钥)加密的Token

    问题描述 在APIM中配置对传入的Token进行预验证,确保传入后端被保护的API的Authorization信息正确有效,可以使用validate-jwt策略.validate-jwt 策略强制要求 ...

  3. P1118 [USACO06FEB]Backward Digit Sums G/S

    P1118 [USACO06FEB]Backward Digit Sums G/S 题解:  (1)暴力法.对1-N这N个数做从小到大的全排列,对每个全排列进行三角形的计算,判断是否等于N.  对每个 ...

  4. VSCode Remote-SSH 连接服务器

  5. PHP的另一个高效缓存扩展:Yac

    之前的文章中我们已经学习过一个 PHP 自带的扩展缓存 Apc ,今天我们来学习另一个缓存扩展:Yac . 什么是 Yac 从名字其实就能看出,这又是鸟哥大神的作品.毕竟是 PHP 的核心开发人员,他 ...

  6. php 常用算法与函数

    1.一群猴子排成一圈,按1,2,-,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去-,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫 ...

  7. 鸿蒙内核源码分析(索引节点篇) | 谁是文件系统最重要的概念 | 百篇博客分析OpenHarmony源码 | v64.01

    百篇博客系列篇.本篇为: v64.xx 鸿蒙内核源码分析(索引节点篇) | 谁是文件系统最重要的概念 | 51.c.h.o 文件系统相关篇为: v62.xx 鸿蒙内核源码分析(文件概念篇) | 为什么 ...

  8. 自从学会了Python自动化Pytest框架,领导再也不敢在我背后指手划脚了

    前言 大家都知道Python有自带的单元测试框架unittest,那为什么还要学习Pytest呢?先了解下Pytest优点 pytest: pytest是一个非常成熟的全功能的Python测试框架,是 ...

  9. bug 找不到或无法加载主类main.java.*

    开发时遇到的的一个问题,不知道是什么引起的,一个maven springboot 的项目,主类启动的时候报错,说没找到 主类,起先怀疑是springboot的问题,随手写一个单独的类,有main方法, ...

  10. JVM类加载器的分类

    类加载器的分类 JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader)和自定义类加载器(User-Defined ClassLoader). 从概念上来讲,自定 ...