深入理解JDK动态代理
1 package jdkproxy; 2 3 public interface Moveable { 4 void move(int i); 5 }
1 package jdkproxy; 2 3 import java.util.Random; 4 5 public class Car implements Moveable { 6 @Override 7 public void move(int i) { 8 try { 9 Thread.sleep(new Random().nextInt(1000)); 10 System.out.println("汽车行驶中..."+i); 11 } catch (InterruptedException e) { 12 e.printStackTrace(); 13 } 14 } 15 16 }
1 package jdkproxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5 6 public class TimeHandler implements InvocationHandler { 7 private Object target; 8 9 public TimeHandler(Object target){ 10 this.target=target; 11 } 12 13 @Override 14 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 15 long start=System.currentTimeMillis(); 16 System.out.println("汽车开始行驶..."); 17 method.invoke(target,args); 18 long end=System.currentTimeMillis(); 19 System.out.println("汽车结束行驶,行驶时间为:"+(end-start)+"毫秒"); 20 return null; 21 } 22 }
1 package jdkproxy; 2 3 import sun.misc.ProxyGenerator; 4 5 import java.io.FileOutputStream; 6 import java.io.IOException; 7 8 public class ProxyGeneratorUtils { 9 public static void writeProxyClassToHardDisk(String path) { 10 byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", Car.class.getInterfaces()); 11 FileOutputStream out = null; 12 try { 13 out = new FileOutputStream(path); 14 out.write(classFile); 15 out.flush(); 16 } catch (Exception e) { 17 e.printStackTrace(); 18 } finally { 19 try { 20 out.close(); 21 } catch (IOException e) { 22 e.printStackTrace(); 23 } 24 } 25 } 26 }
1 package jdkproxy; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Proxy; 5 /* 6 loader:类加载器 7 interfaces:目标对象实现的接口 8 h:InvocationHandler的实现类 9 10 Proxy.newProxyInstance方法: 11 通过getProxyClass0方法生成代理类cl 12 接着通过反射cl.getConstructor.newInstance获取代理类的构造器并生成代理对象 13 14 ProxyGenerator得到JDK生成的$Proxy0.class,再反编译得到的$Proxy0: 15 import java.lang.reflect.InvocationHandler; 16 import java.lang.reflect.Method; 17 import java.lang.reflect.Proxy; 18 import java.lang.reflect.UndeclaredThrowableException; 19 import jdkproxy.Moveable; 20 21 public final class $Proxy0 extends Proxy implements Moveable { 22 private static Method m1; 23 private static Method m2; 24 private static Method m3; 25 private static Method m0; 26 27 public $Proxy0(InvocationHandler var1) throws { 28 super(var1); 29 } 30 31 public final boolean equals(Object var1) throws { 32 try { 33 return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); 34 } catch (RuntimeException | Error var3) { 35 throw var3; 36 } catch (Throwable var4) { 37 throw new UndeclaredThrowableException(var4); 38 } 39 } 40 41 public final String toString() throws { 42 try { 43 return (String)super.h.invoke(this, m2, (Object[])null); 44 } catch (RuntimeException | Error var2) { 45 throw var2; 46 } catch (Throwable var3) { 47 throw new UndeclaredThrowableException(var3); 48 } 49 } 50 51 public final void move(int var1) throws { 52 try { 53 super.h.invoke(this, m3, new Object[]{Integer.valueOf(var1)}); 54 } catch (RuntimeException | Error var3) { 55 throw var3; 56 } catch (Throwable var4) { 57 throw new UndeclaredThrowableException(var4); 58 } 59 } 60 61 public final int hashCode() throws { 62 try { 63 return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); 64 } catch (RuntimeException | Error var2) { 65 throw var2; 66 } catch (Throwable var3) { 67 throw new UndeclaredThrowableException(var3); 68 } 69 } 70 71 static { 72 try { 73 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); 74 m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); 75 m3 = Class.forName("jdkproxy.Moveable").getMethod("move", new Class[]{Integer.TYPE}); 76 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); 77 } catch (NoSuchMethodException var2) { 78 throw new NoSuchMethodError(var2.getMessage()); 79 } catch (ClassNotFoundException var3) { 80 throw new NoClassDefFoundError(var3.getMessage()); 81 } 82 } 83 } 84 85 运行结果: 86 汽车开始行驶... 87 汽车行驶中...1 88 汽车结束行驶,行驶时间为:968毫秒 89 */ 90 public class Test { 91 public static void main(String[] args) { 92 Car car=new Car(); 93 InvocationHandler h=new TimeHandler(car); 94 Moveable m= (Moveable) Proxy.newProxyInstance(car.getClass().getClassLoader(),car.getClass().getInterfaces(),h); 95 m.move(1); 96 ProxyGeneratorUtils.writeProxyClassToHardDisk("D:\\idea\\study\\src\\jdkproxy\\$Proxy0.class"); 97 } 98 }
模拟实现JDK动态代理
1 package com.imooc.proxy; 2 3 public interface Moveable { 4 void move(); 5 }
1 package com.imooc.proxy; 2 3 import java.util.Random; 4 5 public class Car implements Moveable { 6 @Override 7 public void move() { 8 //实现开车 9 try { 10 Thread.sleep(new Random().nextInt(1000)); 11 System.out.println("汽车行驶中...."); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 } 16 17 }
1 package com.imooc.proxy; 2 3 import java.lang.reflect.Method; 4 5 public interface InvocationHandler { 6 void invoke(Object o, Method m); 7 }
1 package com.imooc.proxy; 2 3 import java.lang.reflect.Method; 4 5 public class TimeHandler implements InvocationHandler{ 6 private Object target; 7 8 public TimeHandler(Object target){ 9 this.target=target; 10 } 11 @Override 12 public void invoke(Object o, Method m) { 13 try { 14 long start=System.currentTimeMillis(); 15 System.out.println("汽车开始行驶..."); 16 m.invoke(target); 17 long end=System.currentTimeMillis(); 18 System.out.println("汽车结束行驶,行驶时间为:"+(end-start)+"毫秒"); 19 } catch (Exception e) { 20 e.printStackTrace(); 21 } 22 } 23 }
1 package com.imooc.proxy; 2 3 import org.apache.commons.io.FileUtils; 4 5 import javax.tools.JavaCompiler; 6 import javax.tools.StandardJavaFileManager; 7 import javax.tools.ToolProvider; 8 import java.io.File; 9 import java.lang.reflect.Constructor; 10 import java.lang.reflect.Method; 11 /* 12 生成的代理类$Proxy0 13 package com.imooc.proxy; 14 import java.lang.reflect.Method; 15 public class $Proxy0 implements com.imooc.proxy.Moveable { 16 public $Proxy0(InvocationHandler h){ 17 this.h=h; 18 } 19 private InvocationHandler h; 20 @Override 21 public void move() { 22 try{ 23 Method md=com.imooc.proxy.Moveable.class.getMethod("move"); 24 h.invoke(this,md); 25 }catch(Exception e){ 26 e.printStackTrace(); 27 } 28 } 29 } 30 */ 31 public class Proxy { 32 public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception { 33 String rt="\r\n"; 34 String methodStr=""; 35 for(Method m:infce.getMethods()){ 36 methodStr+= 37 " @Override"+rt+ 38 " public void "+m.getName()+"() {"+rt+ 39 " try{"+rt+ 40 " Method md="+infce.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+ 41 " h.invoke(this,md);"+rt+ 42 " }catch(Exception e){" +rt+ 43 " e.printStackTrace();"+rt+ 44 " }"+rt+ 45 " }"; 46 } 47 String str= 48 "package com.imooc.proxy;"+rt+ 49 "import java.lang.reflect.Method;"+rt+ 50 "public class $Proxy0 implements "+infce.getName()+" {"+rt+ 51 " public $Proxy0(InvocationHandler h){"+rt+ 52 " this.h=h;"+rt+ 53 " }"+rt+ 54 " private InvocationHandler h;"+rt+ 55 methodStr+rt+ 56 "}"; 57 58 //产生代理类的java文件 59 String fileName=System.getProperty("user.dir")+"/bin/com/imooc/proxy/$Proxy0.java"; 60 File file=new File(fileName); 61 FileUtils.writeStringToFile(file,str); 62 63 //拿到编译器 64 JavaCompiler compiler= ToolProvider.getSystemJavaCompiler(); 65 //文件管理者 66 StandardJavaFileManager fileMgr=compiler.getStandardFileManager(null,null,null); 67 //获取文件 68 Iterable units=fileMgr.getJavaFileObjects(fileName); 69 //编译任务 70 JavaCompiler.CompilationTask t=compiler.getTask(null,fileMgr,null,null,null,units); 71 //进行编译 72 t.call(); 73 fileMgr.close(); 74 75 //load到内存 76 Class clazz=ClassLoader.getSystemClassLoader().loadClass("com.imooc.proxy.$Proxy0"); 77 Constructor ctr=clazz.getConstructor(InvocationHandler.class); 78 return ctr.newInstance(h); 79 } 80 81 }
1 package com.imooc.proxy; 2 3 /* 4 汽车开始行驶... 5 汽车行驶中.... 6 汽车结束行驶,行驶时间为:778毫秒 7 */ 8 public class Test { 9 public static void main(String[] args) throws Exception { 10 Car car=new Car(); 11 InvocationHandler h=new TimeHandler(car); 12 Moveable m=(Moveable)Proxy.newProxyInstance(Moveable.class,h); 13 m.move(); 14 } 15 }