深入理解JDK动态代理

Posted sakura1027

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解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 调用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动态代理的主要内容,如果未能解决你的问题,请参考以下文章

深入理解设计模式-代理模式(静态代理动态代理jdk和cglib)

百度T7:深入理解Java动态代理与代码模拟JDK实现动态代理JAVA核心

深入理解JDK动态代理

JDK动态代理 cglib动态代理的深入理解

深入理解Spring AOP之二代理对象生成

深入浅出JDK动态代理