深入理解JDK動態代理
阿新 • • 發佈:2018-04-24
緩存 loader getprop manager 動態 java declared flush ont
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 implementsInvocationHandler { 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(); 16System.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 調用getProxyClass0方法如果緩存中有的話就直接返回,否則會通過ProxyClassFactory類生成 13 ProxyClassFactory類中規定了所有代理類的前綴為$Proxy,接著通過反射 14 cl.getConstructor.newInstance獲取代理類的構造器並生成代理對象 15 16 ProxyGenerator得到JDK生成的$Proxy0.class,再反編譯得到的$Proxy0 17 import java.lang.reflect.InvocationHandler; 18 import java.lang.reflect.Method; 19 import java.lang.reflect.Proxy; 20 import java.lang.reflect.UndeclaredThrowableException; 21 import jdkproxy.Moveable; 22 23 public final class $Proxy0 extends Proxy implements Moveable { 24 private static Method m1; 25 private static Method m2; 26 private static Method m3; 27 private static Method m0; 28 29 public $Proxy0(InvocationHandler var1) throws { 30 super(var1); 31 } 32 33 public final boolean equals(Object var1) throws { 34 try { 35 return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue(); 36 } catch (RuntimeException | Error var3) { 37 throw var3; 38 } catch (Throwable var4) { 39 throw new UndeclaredThrowableException(var4); 40 } 41 } 42 43 public final String toString() throws { 44 try { 45 return (String)super.h.invoke(this, m2, (Object[])null); 46 } catch (RuntimeException | Error var2) { 47 throw var2; 48 } catch (Throwable var3) { 49 throw new UndeclaredThrowableException(var3); 50 } 51 } 52 53 public final void move(int var1) throws { 54 try { 55 super.h.invoke(this, m3, new Object[]{Integer.valueOf(var1)}); 56 } catch (RuntimeException | Error var3) { 57 throw var3; 58 } catch (Throwable var4) { 59 throw new UndeclaredThrowableException(var4); 60 } 61 } 62 63 public final int hashCode() throws { 64 try { 65 return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue(); 66 } catch (RuntimeException | Error var2) { 67 throw var2; 68 } catch (Throwable var3) { 69 throw new UndeclaredThrowableException(var3); 70 } 71 } 72 73 static { 74 try { 75 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")}); 76 m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); 77 m3 = Class.forName("jdkproxy.Moveable").getMethod("move", new Class[]{Integer.TYPE}); 78 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); 79 } catch (NoSuchMethodException var2) { 80 throw new NoSuchMethodError(var2.getMessage()); 81 } catch (ClassNotFoundException var3) { 82 throw new NoClassDefFoundError(var3.getMessage()); 83 } 84 } 85 } 86 87 運行結果: 88 汽車開始行駛... 89 汽車行駛中...1 90 汽車結束行駛,行駛時間為:968毫秒 91 */ 92 public class Test { 93 public static void main(String[] args) { 94 Car car=new Car(); 95 InvocationHandler h=new TimeHandler(car); 96 Moveable m= (Moveable) Proxy.newProxyInstance(car.getClass().getClassLoader(),car.getClass().getInterfaces(),h); 97 m.move(1); 98 ProxyGeneratorUtils.writeProxyClassToHardDisk("D:\\idea\\study\\src\\jdkproxy\\$Proxy0.class"); 99 } 100 }
模擬實現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 public class Proxy { 13 public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception { 14 String rt="\r\n"; 15 String methodStr=""; 16 for(Method m:infce.getMethods()){ 17 methodStr+= 18 " @Override"+rt+ 19 " public void "+m.getName()+"() {"+rt+ 20 " try{"+rt+ 21 " Method md="+infce.getName()+".class.getMethod(\""+m.getName()+"\");"+rt+ 22 " h.invoke(this,md);"+rt+ 23 " }catch(Exception e){" +rt+ 24 " e.printStackTrace();"+rt+ 25 " }"+rt+ 26 " }"; 27 } 28 String str= 29 "package com.imooc.proxy;"+rt+ 30 "import java.lang.reflect.Method;"+rt+ 31 "public class $Proxy0 implements "+infce.getName()+" {"+rt+ 32 " public $Proxy0(InvocationHandler h){"+rt+ 33 " this.h=h;"+rt+ 34 " }"+rt+ 35 " private InvocationHandler h;"+rt+ 36 methodStr+rt+ 37 "}"; 38 39 //產生代理類的java文件 40 String fileName=System.getProperty("user.dir")+"/bin/com/imooc/proxy/$Proxy0.java"; 41 File file=new File(fileName); 42 FileUtils.writeStringToFile(file,str); 43 44 //拿到編譯器 45 JavaCompiler compiler= ToolProvider.getSystemJavaCompiler(); 46 //文件管理者 47 StandardJavaFileManager fileMgr=compiler.getStandardFileManager(null,null,null); 48 //獲取文件 49 Iterable units=fileMgr.getJavaFileObjects(fileName); 50 //編譯任務 51 JavaCompiler.CompilationTask t=compiler.getTask(null,fileMgr,null,null,null,units); 52 //進行編譯 53 t.call(); 54 fileMgr.close(); 55 56 //load到內存 57 Class clazz=ClassLoader.getSystemClassLoader().loadClass("com.imooc.proxy.$Proxy0"); 58 Constructor ctr=clazz.getConstructor(InvocationHandler.class); 59 return ctr.newInstance(h); 60 } 61 62 }
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 }
深入理解JDK動態代理