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