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. Oracle体系结构二

  2. ClickOnce手动更新

    if (ApplicationDeployment.IsNetworkDeployed == true)             {                 ApplicationDeploy ...

  3. python中字符串的各种方法

     图片来源见水印,一个学python的公众号

  4. java的split方法中的regex参数

    我们需要以|进行分割,为了匹配|本身,正则中采用\|进行转义,而Java中\也表示转义,从java到正则需要必须使用\\|进行转义,即split中的\\表示正则的转义.

  5. python类、对象

    python类.对象 学习完本篇,你将会深入掌握 什么是类,对象 了解类和对象之间的关系 能独立创建一个People(人类),属性有姓名.性别.年龄.提供一个有参的构造方法,编写一个show方法,输出 ...

  6. js判断苹果端,安卓端

    <script type="text/javascript"> var browser = { versions : function() { var u = navi ...

  7. 学会了这些英文单词,妈妈再也不用担心我学不会Python

    前言   很多转行或刚入行做测试的小伙伴学习Python时,经常会问一句话:我英语不好能不能学会代码. 答案是:肯定的!你如果英语好学开发语言肯定要比不会英语的小伙伴学起来.当代码报错时全是英文,毕竟 ...

  8. BATJ经典软件测试面试题我连答案都告诉你了,如果你不想月薪上万,那你别看!

    单项选择题:共20小题,每小题1 分,满分20分:请将答案填入题后括号中. 1. 在软件生命周期的哪一个阶段,软件缺陷修复费用最低(A) A.需求分析(编制产品说明书)    B.设计 C.编码    ...

  9. 怒肝 Linux 学习路线,这回不难

    Linux 学习路线 by 鱼皮. 原创不易,请勿抄袭,违者必究! 大家好,我是鱼皮,又花 1 周肝出了 Linux 学习资料全家桶,包括学习路线.命令手册.视频.书籍.文档.实战教程.社区.工具.大 ...

  10. Linux下iptables学习笔记

    Linux下iptables学习笔记 在Centos7版本之后,防火墙应用已经由从前的iptables转变为firewall这款应用了.但是,当今绝大多数的Linux版本(特别是企业中)还是使用的6. ...