博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JDK动态代理详解
阅读量:6320 次
发布时间:2019-06-22

本文共 3470 字,大约阅读时间需要 11 分钟。

hot3.png

生成代理类:

Class proxyClass = Proxy.getProxyClass(ClassLoader loader, Class
... interfaces);

这段代码生成一个代理类,该代理类拥有一个参数类型为InvocationHandler的构造方法,用以构造代理对象,如下:   

Object proxyInstance = proxyClass.getConstructor(InvocationHandler.class).newInstance(new MyInvocationHandler(...));

   以上步骤合并,就可以是以下更简单的形式:

Object proxyInstance = Proxy.newInstance(ClassLoader loader, Class
[] interfaces, InvocationHandler h);

   其中的原理:

   1、生成代理类字节码:

byte[] proxyClassFile = ProxyGenerator.generateProxyClass(String proxyName, Class
[] interfaces, int accessFlags);

      这里ProxyGenerator.generateProxyClass方法直接根据指定的代理类名称、接口列表和类的访问修饰符生成代理类的字节码文件;

      生成的代理类会继承java.lang.reflect.Proxy类,实现参数指定的接口。代理类会实现所有接口方法并覆盖Object的equals、hashCode、toString方法。
      代理类本身和它定义的所有方法都是final的,包括equals、hashCode、toString。
   2、代理类中的每个方法,都有一个static Method对象与之关联,包括:equals、hashCode、toString,在这里我理解Method对象仅仅是一个方法描述符而已,它描述了方法的名称、形参列表、返回值、访问标识符和声明这个方法的Class等信息。
   3、根据以上代理对象生成代码,在生成代理对象时需要传入一个InvocationHandler对象,在代理类中,对所有方法的调用都会通过以下代码委托到对InvocationHandler对象的调用:
      super.h.invoke(this, method, new Object[] { ... });
      其中super.h是指Proxy类中的h属性字段,就是生成代理对象时传入的InvocationHandler对象;
      参数1为代理对象本身,参数2为调用的方法对象(对应于代理对象中声明的相应static Method对象),参数3为调用的方法的参数数组。

代理类示例(生成字节码后通过jad反编译后调整格式):

package why.jvm.dynamicProxy;import java.lang.reflect.*;import why.jvm.dynamicProxy.FinaTradeService;public final class MyProxyClass extends Proxy implements FinaTradeService {	private static Method m1;	private static Method m3;	private static Method m2;	private static Method m4;	private static Method m0;	static {		try {			m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);			m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });			m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);			m3 = Class.forName("why.jvm.dynamicProxy.FinaTradeService").getMethod("placeOrder", new Class[] { Class.forName("java.lang.String") });			m4 = Class.forName("why.jvm.dynamicProxy.FinaTradeService").getMethod("createOrder", new Class[] { Class.forName("java.lang.String") });		} catch (NoSuchMethodException nosuchmethodexception) {			throw new NoSuchMethodError(nosuchmethodexception.getMessage());		} catch (ClassNotFoundException classnotfoundexception) {			throw new NoClassDefFoundError(classnotfoundexception.getMessage());		}	}	public MyProxyClass(InvocationHandler invocationhandler) {		super(invocationhandler);	}	public final int hashCode() {		try {			return ((Integer) super.h.invoke(this, m0, null)).intValue();		} catch (Throwable throwable) {			throw new UndeclaredThrowableException(throwable);		}	}	public final boolean equals(Object obj) {		try {			return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })).booleanValue();		} catch (Throwable throwable) {			throw new UndeclaredThrowableException(throwable);		}	}	public final String toString() {		try {			return (String) super.h.invoke(this, m2, null);		} catch (Throwable throwable) {			throw new UndeclaredThrowableException(throwable);		}	}	public final String createOrder(String s) {		try {			return (String) super.h.invoke(this, m4, new Object[] { s });		} catch (Throwable throwable) {			throw new UndeclaredThrowableException(throwable);		}	}	public final String placeOrder(String s) {		try {			return (String) super.h.invoke(this, m3, new Object[] { s });		} catch (Throwable throwable) {			throw new UndeclaredThrowableException(throwable);		}	}}

 

转载于:https://my.oschina.net/mojiewhy/blog/1818002

你可能感兴趣的文章
LeetCode Container With Most Water (Two Pointers)
查看>>
vue (v-if show 问题)
查看>>
https基础
查看>>
RESTful Mongodb
查看>>
如何提高Ajax性能
查看>>
Android--自定义加载框
查看>>
LINUX下 lamp安装及配置
查看>>
BZOJ3105 [cqoi2013]新Nim游戏
查看>>
困惑的前置操作与后置操作
查看>>
BZOJ 2118 Dijkstra
查看>>
Jenkins
查看>>
linux下使用screen和ping命令对网络质量进行监控
查看>>
数据库设计技巧
查看>>
css定位概述
查看>>
segment
查看>>
面试/编程
查看>>
打造一个上传图片到图床利器的插件(Mac版 开源)
查看>>
thinkphp判断更新是否成功
查看>>
高效使用jquery之一:请使用'On'函数
查看>>
NuGet学习笔记(2)——使用图形化界面打包自己的类库
查看>>