探索Mybatis之JDK动态代理:探究Proxy.newProxyInstance()生成的代理类解析

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

原文地址:https://www.cnblogs.com/magic-sea/p/11229237.html

时间: 2024-10-03 01:34:10

探索Mybatis之JDK动态代理:探究Proxy.newProxyInstance()生成的代理类解析的相关文章

设计模式 - 代理模式(proxy pattern) 未使用代理模式 详解

代理模式(proxy pattern) 未使用代理模式 详解 本文地址: http://blog.csdn.net/caroline_wendy 部分代码参考: http://blog.csdn.net/caroline_wendy/article/details/37698747 如果需要监控(monitor)类的某些状态, 则需要编写一个监控类, 并同过监控类进行监控. 但仅仅局限于本地, 如果需要远程监控, 则需要使用代理模式(proxy pattern). 具体方法: 1. 类中需要提供

Java 动态代理 调用Proxy.newProxyInstance()

一.概述 1.目标:不自己写代理类,利用Proxy.newProxyInstance()动态生成 2.用到的知识点: (1)//编译源码,生成class,注意编译环境要换成jdk才有compiler,单纯的jre没有compiler,会空指针错误 JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); (2)//文件管事器 StandardJavaFileManager fileMgr = jc.getStandardFileManager

Java之美[从菜鸟到高手演练]之JDK动态代理的实现及原理

JDK动态代理的实现及原理 作者:二青 邮箱:[email protected]     微博:http://weibo.com/xtfggef 动态代理,听上去很高大上的技术,在Java里应用广泛,尤其是在Hibernate和Spring这两种框架里,在AOP,权限控制,事务管理等方面都有动态代理的实现.JDK本身有实现动态代理技术,但是略有限制,即被代理的类必须实现某个接口,否则无法使用JDK自带的动态代理,因此,如果不满足条件,就只能使用另一种更加灵活,功能更加强大的动态代理技术-- CG

关于JDK动态代理和CGLIB动态代理

1. 代理模式 一句话总结:为其他对象提供一种代理以控制对这个对象的访问.千篇一律的介绍:代理模式是常用的java设计模式,他的特征是代理类与委托类(或目标类)有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工具

java JDK动态代理的机制

一:前言 自己在稳固spring的一些特性的时候在网上看到了遮掩的一句话“利用接口的方式,spring aop将默认通过JDK的动态代理来实现代理类,不适用接口时spring aop将使用通过cglib 来实现代理类",我对JDK的动态代理机制其实一点都不了解,学习java的时候也是只是知道会用,会去查api的文档就行,所以这些底层的操作方式我自己不是很清楚,现在既然要了解一些底层的代码,就谢谢自己的想发,大部分都是差不多的. 二:实现 先给出接口和实现类的代码: UserDao.java: p

基于Spring AOP的JDK动态代理和CGLIB代理

一.AOP的概念  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 二.主要用途 将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务

JDK动态代理连接池

JDK动态代理 ? 1 什么是JDK动态代理 刚刚写ItcastConnection时爽么?因为Connection中的方法太多了,每个都要写,所以很累吧.累点到是没什么,可以完成功能就是好的.但是不是什么时候可以用代理的,有时你可能会遇到要代理的东西,只有在运行时才能知道,所以你不可能先把代理写出来!这时就需要使用动态代理. JDK动态代理是JavaSE中一个高级特性,不是那么好理解的,但是它可是框架们的"秘密武器".你要是可以理解它,那么将来在学习框架时,你就会知道框架是怎么完成一

spring aop原理 JDK动态代理和CGLIB动态代理

Spring的两大特性是IOC和AOPIOC负责将对象动态的注入到容器,从而达到一种需要谁就注入谁,什么时候需要就什么时候注入的效果.理解spring的ioc也很重要.但是今天主要来和大家讲讲aop.AOP 广泛应用于处理一些具有横切性质的系统级服务,AOP 的出现是对 OOP 的良好补充,用于处理系统中分布于各个模块的横切关注点,比如事务管理.日志.缓存等等. AOP实现的关键在于AOP框架自动创建的AOP代理.AOP代理主要分为静态代理和动态代理, 静态代理的代表为AspectJ:动态代理则

动态代理模式——JDK动态代理

今天,我就来讲一下动态代理的设计模式. 动态代理的意义在于生成一个代理对象,来代理真实对象,从而控制真实对象的访问.操作动态代理需要两个步骤:一.代理对象和真实对象建立代理关系.二.实现代理对象的代理逻辑方法. 在Java中,有很多的动态代理技术.如:JDK.CGLIB.Javassist.ASM,其中最常用的动态代理技术有两种:一种是JDK动态代理,这是JDK自带的功能:另一种就是CGLIB,这是第三方提供的一种技术. 这次主要讲的是JDK动态代理和CGLIB动态代理.在JDK动态代理中,我们