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的操作。