1. 程式人生 > >深入理解JDK動態代理

深入理解JDK動態代理

緩存 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 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 調用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動態代理