关于jdk的proxy看了几遍,每次记住了,过了一段时间,又容易忘记 java
今天仔细看了一下,发现实际上Proxy.newInstance就是动态生成了一个Proxy.class文件,而后我用jad反编译以后发现,就是生成了一个类,implement以前写的interface,而后全部的方法都写成final了 数组
反编译后代码以下 this
public final int say(String s, String s1) { try { return ((Integer)super.h.invoke(this, m3, new Object[] { s, s1 })).intValue(); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final ArrayList list(String s, int i) { try { return (ArrayList)super.h.invoke(this, m4, new Object[] { s, Integer.valueOf(i) }); } catch(Error _ex) { } catch(Throwable throwable) { throw new UndeclaredThrowableException(throwable); } }
如今代理类生成了,如何调用hander里面的invoke呢 代理
步骤1.Class cl = getProxyClass(loader, interfaces); 获取代理类的class code
步骤2.Constructor cons = cl.getConstructor(constructorParams); 获取proxy的子类的构造方法 对象
constructorParams 的值为 new class[]{invocationhandler.class}; 继承
步骤3.获取实体类对象 接口
return (Object) cons.newInstance(new Object[] { h }); get
由于生成的代理类继承Proxy,实现了咱们传进去的接口,全部接口执行方法,直接调用生成的Proxy里面的final方法,返回结果就是,调用传进去的handler的invoke方法,参数this, it
return (ArrayList)super.h.invoke(this, m4, new Object[] { s, Integer.valueOf(i) }); 第一个参数就是当前Proxy,第二个是方法Method,第三个是args
还有Object... args这种参数实际上编译之后是object[] 数组,是java的语法糖
而后就执行咱们的handler里面定义的invoke方法了
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("aaa:"+proxy.getClass().getName()); Object temp =method.invoke(this.o, args); return temp; }
如下附java生成字节码方法:
public class ProxyGeneratorUtils { /** * 把代理类的字节码写到硬盘上 * @param path 保存路径 */ public static void writeProxyClassToHardDisk(String path) { // 第一种方法,这种方式在刚才分析ProxyGenerator时已经知道了 // System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true); // 第二种方法 // 获取代理类的字节码 byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", SujectImpl.class.getInterfaces()); FileOutputStream out = null; try { out = new FileOutputStream(path); out.write(classFile); out.flush(); } catch (Exception e) { e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { ProxyGeneratorUtils.writeProxyClassToHardDisk("F:/$Proxy11.class"); } }你们能够试一下