这里的内容就比较复杂了,要实现的是对任意的接口,对任意指定的方法,以及对任意指定的代理类型进行代理,就更真实的模拟出java虚拟机的动态代理机制

罗列一下这里涉及的类、接口之间的关系,方便大家学习。
1、InvocationHandler接口,用来处理指定的方法,即对特定方法的代理,处理的具体实现交由子类实现
2、TimeHandler类,实现了InvocationHandler接口的子类,具体的代理实现是进行时间代理
3、Proxy类,用于产生代理类的类
4、Moveable接口,举例过程中各类要实现的统一接口
5、Tank类,实现了Moveable接口,即被代理的类
6、Cilent,操作客户端

先把整个的思路理一下:
首先在Client端,new一个被代理的对象Tank,Tank对象作为构造参数传入代理处理类TimeHandler,new出一个TimeHandler对象,
Tank的接口Moveable和TimeHandler对象作为参数传入Proxy,Proxy调用newProxyInstance方法,该方法中对接口的所有的方法,利用TimeHandler对象进行代理,(可以简单理解为将接口方法与TimeHandler代理方法结合),生成新的代理对象的java文件、class文件、然后加载进入内存,利用反射获得一个代理对象,返回该代理对象,在Client端调用则调用了代理对象方法;


1、InvocationHandler接口

1 package com.csu.proxy;
2
3 import java.lang.reflect.Method;
4 //对任意方法自定义处理
5 //方法调用的处理器
6 public interface InvocationHandler {   //定义一个接口,用来处理方法,处理的具体实现交由子类实现
7
8     public void invoke(Object o, Method m);  //对某个指定方法的处理
9 }

2、TimeHandler类

 1 package com.csu.proxy;
 2
 3 import java.lang.reflect.Method;
 4 public class TimeHandler implements InvocationHandler {
 5    private Object target;//被代理的对象
 6
 7     public Object getT() {
 8         return target;
 9     }
10
11     public void setT(Object t) {
12         this.target = t;
13     }
14
15     public TimeHandler(Object target) {
16         this.target = target;
17     }
18
19     @Override
20     public void invoke(Object o,Method m){  //必须指定具体对象对具体的方法的调用
21         long start = System.currentTimeMillis();
22         System.out.println("start time is " + start);
23         System.out.println(o.getClass().getName());
24         //m 调用方法
25         try {
26             m.invoke(target);
27         } catch (Exception e) {e.printStackTrace();}
28
29
30         long end = System.currentTimeMillis();
31         System.out.println("end time is "+end);
32         System.out.println("time is "+(end - start));
33     }
34 }


3、Moveable接口

1 package com.csu.proxy;
2
3 public interface Moveable {
4     void move();
5 }

4、Tank类

 1 package com.csu.proxy;
 2
 3 import java.util.Random;
 4
 5
 6 public class Tank implements Moveable {
 7
 8     @Override
 9     public void move() {
10
11         System.out.println("Tank Moving...");
12         try {
13             Thread.sleep(new Random().nextInt(10000));
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17
18     }
19
20 }

5、Proxy类

  1 package com.csu.proxy;
  2
  3 import javax.tools.JavaCompiler;
  4 import javax.tools.StandardJavaFileManager;
  5 import javax.tools.ToolProvider;
  6 import java.io.File;
  7 import java.io.FileWriter;
  8 import java.lang.reflect.Constructor;
  9 import java.lang.reflect.Method;
 10 import java.net.URL;
 11 import java.net.URLClassLoader;
 12
 13 /**
 14 方便大家阅读,关注主要的逻辑思路,将在前面博客的已经写过的注释代码清除,因为这是一系列,有很多代码引用
 15 有想要看的,去上几篇文章看吧
 16 **/
 17
 18 //该类要实现对任意接口,任意方法,以及任意的代理 的实现
 19 public class ProxyG3 {
 20     public static Object newProxyInstance(Class intf, InvocationHandler h) throws Exception{
 21     //invocationHandler当成参数,指定代理的类型,即指定对方法要进行什么处理
 22
 23         //*****************1、获得java文件**********************************
 24     String methodsString = "";
 25         String rt = "\r\n";
 26
 27         Method[] methods = intf.getMethods();
 28         for(Method m : methods) {
 29             methodsString += "@Override" + rt +
 30                     "public void " + m.getName() + "() {" + rt +
 31                     "    try {" + rt +
 32                     "    Method md = " + intf.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt +
 33                     "    h.invoke(this, md);" + rt +
 34                     "    }catch(Exception e) {e.printStackTrace();}" + rt +
 35
 36                     "}";
 37         }
 38
 39         String src =
 40                         "package com.csu.proxy;" +  rt +
 41                         "import java.lang.reflect.Method;" + rt +
 42                         "public class TankTimeProxy implements " + intf.getName() + "{" + rt +
 43                         "    public TankTimeProxy(InvocationHandler h) {" + rt +
 44                         "        this.h = h;" + rt +
 45                         "    }" + rt +
 46
 47
 48                         "    com.csu.proxy.InvocationHandler h;" + rt +
 49
 50                         methodsString +
 51                         "}";
 52         String fileName = "g:/src/com/csu/proxy/TankTimeProxy.java";//放在指定的地方
 53         File f = new File(fileName);
 54         FileWriter fw = new FileWriter(f);
 55         fw.write(src);
 56         fw.flush();
 57         fw.close();
 58     /**
 59     这里重点说一下:用于存放代理对象TankTimeProxy的java和class文件的包名要工程中的其他java文件的包名一致,查看代码你会发现
 60     工程的java文件和生成的代理对象的java文件的包名都是 com.csu.proxy;
 61     **/
 62
 63         //****************2、获得class文件****************************************
 64
 65      //获得编译器对象
 66         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 67
 68         //管理动态生成的文件
 69         StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,null,null);
 70         Iterable units = fileManager.getJavaFileObjects(fileName);
 71
 72         //“编译任务”对象
 73         JavaCompiler.CompilationTask task = compiler.getTask(null,fileManager,null,null,null,units);
 74         task.call();
 75         fileManager.close();
 76
 77         //*****************3、加载至内存******************************************
 78
 79         //通过Url引入本地文件
 80         URL[] urls = new URL[]{new URL("file:/"+"g:/src/")}; //访问本地文件   指定class文件存放的位置
 81         URLClassLoader urlClassLoader = new URLClassLoader(urls);
 82         Class c = urlClassLoader.loadClass("com.csu.proxy.TankTimeProxy");
 83
 84         //******************4、执行class文件,返回代理对象***************************************
 85
 86         //获得构造方法
 87         Constructor constructor = c.getConstructor(InvocationHandler.class);  //getConstructor的参数为Class类型,是原构造方法的参数的Class类型
 88
 89         //产生新对象
 90         Object m =  constructor.newInstance(h);
 91
 92         return m;
 93     }
 94 }
 95
 96 6、Cilent客户端
 97
 98 package com.csu.proxy;
 99
100 public class Client {
101     public static void main(String[] args) throws Exception {
102
103         Tank t = new Tank();
104         InvocationHandler h = new TimeHandler(t);
105
106         Moveable m =(Moveable) ProxyG3.newProxyInstance(Moveable.class, h);
107
108         m.move();
109
110
111     }
112 }

 

7、执行结果

(1)生成的java和class文件

(2)查看生成的java文件代码

(3)运行结果

转载于:https://www.cnblogs.com/chentao-cus/p/4817584.html

深度模拟java动态代理实现机制系类之三相关推荐

  1. 深度解析JAVA动态代理设计模式

    基本概念:Proxy模式也叫代理模式,所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类,客户端必须通过代理与被代理的目标类交互,而代理一般在交互的过程中(交互前后),进行某些特别的处理(比 ...

  2. Java 动态代理机制分析及扩展--转

    http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/#icomments http://www.ibm.com/developerworks/c ...

  3. Java 动态代理机制分析及扩展,第 1 部分

    引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执 ...

  4. Java 动态代理机制分析及扩展

    简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟推演了动态代理类的可能实现,向读者阐述了一个完整的 Java 动态代理运作过程,希望能帮助读者加深对 Java 动 ...

  5. Java 动态代理及 RPC 框架介绍

    所谓动态代理,指的是语言提供的一种语法,能够将对对象中不同方法的调用重定向到一个统一的处理函数中来. python重写__getattr__函数能够做到这一点,就连世界上最好的语言也提供称为魔术方法的 ...

  6. java 动态代理深度学习(Proxy,InvocationHandler)

    http://hi.baidu.com/malecu/item/9e0edc115cb597a1feded5a0 http://www.iteye.com/topic/683613 http://bl ...

  7. Java动态代理机制详解(JDK 和CGLIB,Javassist,ASM)

    class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出 ...

  8. Java 动态代理机制详解

    在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的 ...

  9. Java动态代理机制详解

    class文件简介及加载 Java编译器编译好Java文件之后,产生.class 文件在磁盘中.这种class文件是二进制文件,内容是只有JVM虚拟机能够识别的机器码.JVM虚拟机读取字节码文件,取出 ...

最新文章

  1. 中国芯片将靠此超车!RISC-V架构神在哪全解构【附下载】
  2. 一元多项式的乘法与加法运算_行测数学运算之速算与技巧
  3. Java学习|先定一个小目标比如让行为聚焦
  4. 【Linux】36.ubuntu删除vscode的缓存,可清理出几十G空间
  5. JOptionPane的常用4种对话框
  6. Python爬虫-代理ip池建立
  7. 整合百度UEditor上传图片到阿里云OSS
  8. 软件构造学习笔记-第七周
  9. 如果连这10个Python缩写都不知道,那你一定是Python新手
  10. thinkphp htmls.php,ThinkPHP静态缓存简单配置和使用方法详解
  11. 买手机数据线特别要注意的地方
  12. python下载过程中最后一步执行opencv出错怎么回事_PyCharm安装opencv-python和opencv-contrib-python的一些问题和解决方法_2018-09-27...
  13. std在汇编语言是什么指令_汇编语言STD CLD的用法
  14. Golang获取时间戳并增加一天
  15. Ubuntu-图形界面和字符界面切换快捷键
  16. 微创新:粉丝电子商务及微博的9种盈利模式
  17. 通过漫画学习MySQL索引及优化
  18. Java线程死锁模拟
  19. excel基于一列的值统计另一列数值的个数
  20. 【CXY】JAVA基础 之 Collection

热门文章

  1. Session在类库中的使用
  2. 基于java的http服务器
  3. java 把URL中的中文转换成utf-8编码
  4. Android中解析XML---数据存储
  5. java.io.IOException cannot be resolved
  6. 通过WiFi调试android手机
  7. 11月22日弹性计算跟您在广州不见不散
  8. 2016-08-05
  9. python学习笔记5—数据类型转换
  10. postfix本机测试本机时,telnet连接出错