上一篇博客是最基本的动态代理原理的实现,因为其固定了接口,固定了代理方法,以及固定了代理的类型,
接下来的博客系类将一步步渐入深度介绍java的动态代理的实现原理

****************************************************************************
首先补充一下“java代理”的相关知识,静态代理的实现包括两种方式,一是聚合,另一种是继承。
聚合是指通过接口,调用其实现类的具体方法:比如接口i,含有方法run(); 类A 实现了接口i,当然
也实现了方法run(); 类B于是就可以通过new一个接口 i 的对象,调用A的run()方法,并在run()方法前后实现其他操作,
这样就实现了对A的run()方法的代理;
继承当然更好理解,就是把run()方法重写,从而实现代理
但是,一旦代理的操作很多,需要写的类都非常的繁杂,就需要不断的写代理类,不断的更新代理操作,于是这就有了动
态代理。

*****************************************************************************

这次要对实现任意接口的类进行代理。

1、接口

public interface Moveable {
void move();
}

  

2、被代理的对象

 public class Tank implements Moveable {

     @Override
public void move() { System.out.println("Tank Moving...");
try {
Thread.sleep(new Random().nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
} } }

3、用于产生代理对象

 public class Proxy {
//产生新的动态代理类
public static Object newProxyInstance(Class intf) throws Exception{ //将接口当成参数传入,这样就可以代理实现了任意接口的类,而不仅是实现了Moveable接口
//将一下字符串动态编译,生成代理类
//实现方式有以下击中:jdk6.0 complier API;CGLib; ASM
String rt = "\r\n";
String src =
"public class TankTimeProxy implements " +intf.getName()+ "{"+rt+ //直接用intf,是调用toString方法,前会加入字符串 interface
intf.getName()+" t;"+rt+ " public TankTimeProxy("+intf.getName()+" t) {"+rt+
" this.t = t;"+rt+
" }"+rt+ " @Override"+rt+
" public void move() {"+rt+
" long start = System.currentTimeMillis();"+rt+
" System.out.println(\"start time is \"+start);"+rt+
" t.move();"+rt+
" long end = System.currentTimeMillis();"+rt+
" System.out.println(\"end time is \"+end);"+rt+
" System.out.println(\"time is \"+(end - start));"+rt+
" }"+rt+
"}"; //进行编译
String fileName = "g:/src/TankTimeProxy.java";//将文件另外存储,不放置在工程的默认路径,防止缓冲区相关类的冲突
File f = new File(fileName);
FileWriter fw = new FileWriter(f);
//System.out.println(fileName);
fw.write(src); //写入内容 fw.flush();
fw.close(); //进行编译
//首先获得编译器
//compiler 为java编译器 javac
//获得编译器对象
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
//System.out.println(compiler.getClass().getName());//取得类名
//参数含义 (编译诊断,locale,charset)
//管理动态生成的文件
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,null,null);//默认值
//根据参数获取多个java文件 返回java文件对象
Iterable units = fileManager.getJavaFileObjects(fileName); //“编译任务”对象
JavaCompiler.CompilationTask task = compiler.getTask(null,fileManager,null,null,null,units);
task.call();//调用
fileManager.close(); //************以上过程获得了java文件源码,编译生成了java文件的class文件*******
//加载至内存,生成新对象
//Class.load(0 是加载path路径的class文件
//URLClassLoader是将硬盘中的class文件加载进入 //通过Url引入本地文件
URL[] urls = new URL[]{new URL("file:/"+"g:/src/")}; //指定生成class文件的位置,与java文件放置在同一目录
//去指定路径寻找class文件
URLClassLoader urlClassLoader = new URLClassLoader(urls); Class c = urlClassLoader.loadClass("TankTimeProxy"); System.out.println(c); //执行
//c.newInstance(); 是调用空的构造方法 //获得构造方法
//根据java虚拟机,每一个构造方法也相当于一个对象
Constructor constructor = c.getConstructor(intf); //产生新对象
Moveable m = (Moveable) constructor.newInstance(new Tank()); //new Tank()为构造方法的参数 即被代理对象 m.move(); return m;
}
}

4、测试端

 public class Client {
public static void main(String[] args) throws Exception { //这里任然以Moveable接口为例传入,因为在Proxy中为节省麻烦,还是固定生成了Moveable,后来会慢慢简化的,其实是可以传递任意的的接口的
Moveable m =(Moveable) Proxy.newProxyInstance(Moveable.class);
m.move(); }
}

5、结果

(1)生成的java与class文件

(2)java文件的代码

(3)运行结果

深度模拟java动态代理实现机制系类之一的更多相关文章

  1. 深度模拟java动态代理实现机制系类之三

    这里的内容就比较复杂了,要实现的是对任意的接口,对任意指定的方法,以及对任意指定的代理类型进行代理,就更真实的模拟出java虚拟机的动态代理机制 罗列一下这里涉及的类.接口之间的关系,方便大家学习.1 ...

  2. 深度模拟java动态代理实现机制系类之二

    这次我们要实现的是对任意接口,任意的方法进行特定的代理 这里不一样的只有Proxy类,要实现对所有方法进行代理,那么重点就在于获得接口的所有方法 import java.io.File; import ...

  3. 透过字节码生成审视Java动态代理运作机制

    对于动态代理我想应该大家都不陌生,就是可以动态去代理实现某个接口的类来干一些我们自己想要的功能,但是在字节码层面它的表现是如何的呢?既然目前刚好在研究字节码相关的东东,有必要对其从字节码角度来审视一下 ...

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

    Java 动态代理机制分析及扩展,第 1 部分 王 忠平, 软件工程师, IBM 何 平, 软件工程师, IBM 简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟 ...

  5. [转]Java 动态代理机制分析及扩展

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

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

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

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

    Java 动态代理机制分析及扩展,第 1 部分 http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/ 本文通过分析 Java 动态代理的机制和特 ...

  8. JAVA动态代理的全面深层理解

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

  9. 一文读懂Java动态代理

    作者 :潘潘 日期 :2020-11-22 事实上,对于很多Java编程人员来说,可能只需要达到从入门到上手的编程水准,就能很好的完成大部分研发工作.除非自己强主动获取,或者工作倒逼你学习,否则我们好 ...

随机推荐

  1. MyBatis简介与配置MyBatis+Spring+MySql

    MyBatis学习 之 一.MyBatis简介与配置MyBatis+Spring+MySql MyBatis学习 之 二.SQL语句映射文件(1)resultMap MyBatis学习 之 二.SQL ...

  2. STL 源代码剖析 算法 stl_algo.h -- lower_bound

    本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie lower_bound(应用于有序区间) ------------------------- ...

  3. ThinkPHP3.1快速入门(12)自动验证

    自动验证是ThinkPHP模型层提供的一种数据验证方法,可以在使用create创建数据对象的时候自动进行数据验证. 验证规则 数据验证可以进行数据类型.业务规则.安全判断等方面的验证操作.数据验证有两 ...

  4. mysql下命令行执行sql脚本

    1. 登录mysql mysql -uroot -p 2. 执行脚本 mysql>use dbname; mysql>source /home/db/xx.sql

  5. Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 44 bytes) in

    最近莫名出现这个错误. 研究一下原因很奇葩呢. 原因:sql获取数据库中数据,取出数据赋给变量,数据太多,超过memory_limit内存设置了. 解决方法:设置memory_limit不建议.优化代 ...

  6. .TextOut文字保存为图片

    //Canvas.TextOut文字保存为图片 //Delphi开发案例精选,使用TextOut在画布上画图procedure TForm1.Button1Click(Sender: TObject) ...

  7. 《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记

    造成开销的操作包含: 1. 线程之间的协调(比如:锁.触发信号以及内存同步等) 2. 添加�的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 执行速度涉及下 ...

  8. UITableViewCell 高度自适应

    UITableViewCell 高度自适应一直是我们做动态Cell高度时遇到的最烦躁的问题,Cell动态高度计算可以去看看sunny的这篇文章介绍,今天主要和大家分享下我在使用systemLayout ...

  9. Git链接到自己的Github(2)进阶使用

    接着上一篇的,从github clone下代码. 1.先查看当前开发分支 $ cat .git/HEAD ref: refs/heads/master 这里的master是默认分支. 2.查看当前状态 ...

  10. UNIX标准化及实现之标准之间的冲突

    就整体而言,这些不同的标准之间配合得相当好.但是我们也很关注它们之间的差别,特别是ISO C标准和POSIX.1之间的差别. ISO C定义了函数clock,它返回进程使用的CPU时间,返回值类型是c ...