深入理解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 }

 

全部评论

相关推荐

咦哟,从去年八月份开始长跑,两处实习转正都失败了,风雨飘摇,终于拿到offer了更新一下面试记录:秋招:多部门反复面试然后挂掉然后复活,具体问了啥已经忘了,只是被反复煎炸,直至焦香😋春招:base北京抖音hr打来电话说再次复活,准备面试,gogogo北京抖音一面:六道笔试题:1.promise顺序2.定义域问题3.flat展开4.并发请求5.岛屿数量算法(力扣)深度,广度都写6.忘记了,好像也是算法,难度中等其他问题多是框架底层设计,实习项目重难点~~~秒过😇北京抖音二面:三道笔试题:(为什么只有三道是因为第三道没做出来,卡住了)1.中等难度算法(忘记啥题了,应该是个数组的)2.认识js的继承本质(手写继承模式,深入js的面相对象开发)3.手写vue的响应式(卡在了watch,导致挂掉)---后知后觉是我的注册副作用函数写得有问题,有点紧张了其他题目多是项目拷打,项目亮点,对实习项目的贡献~~~第二天,挂,but立马复活转战深圳客服当天约面深圳客服一面:六道笔试题,由于面过太多次字节,面试官叫我直接写,不用讲,快些写完😋,具体都是些继承,深拷贝(注意对数组对象分开处理,深层次对象,循环引用),加中等难度算法题~~~秒过深圳客服二面:口诉八股大战:大概囊括网络,浏览器渲染原理,动画优化,时间循环,任务队列等等(你能想到的简单八股通通拉出来鞭尸😋)算法题:笔试题6道:1:找出数组内重复的数,arr[0]-arr[n]内的数大小为[1-n],例如[1,2,2,3,3]返回[2,3],要求o(n),且不使用任何额外空间(做到了o(n),空间方面欠佳,给面试官说进入下一题,做不来了)2:原滋原味的继承(所以继承真滴很重要)3:力扣股票购买时机难度中等其他滴也忘记了,因为拿到offer后鼠鼠一下子就落地了,脑子自动过滤掉可能会攻击鼠鼠的记忆😷~~~秒过深圳客服三面:项目大战参与战斗的人员有:成员1:表单封装及其底层原理,使用成本的优化,声明式表单成员2:公司内部库生命周期管理成员3:第三方库和内部库冲突如何源码断点调试并打补丁解决成员4:埋点的艺术成员5:线上项目捷报频传如何查出内鬼成员6:大文件分片的风流趣事成员7:设计模式对对碰成员8:我构建hooks应对经理的新增的小需求的故事可能项目回答的比较流利,笔试题3道,都很简单,相信大家应该都可以手拿把掐😇~~~过过过无hr面后续煎熬等待几天直接hr打电话发offer了,希望大家也可以拿到自己心仪的offer
法力无边年:牛哇,你真是准备得充分,我对你没有嫉妒,都是实打实付出
查看19道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务