码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2015-09-17 19:32:56      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:

这次我们要实现的是对任意接口,任意的方法进行特定的代理

这里不一样的只有Proxy类,要实现对所有方法进行代理,那么重点就在于获得接口的所有方法

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;

//该类实现了对任意接口,任意方法的特定代理
public class ProxyG2 {
    //产生新的动态代理类
    public static Object newProxyInstance(Class intf) throws Exception{  //将接口当成参数传入,这样就可以代理实现了任意接口的类,而不仅是实现了Moveable接口
        String methodsString = "";  //获得所有方法字符串
        String rt = "\r\n";

        Method[] methods = intf.getMethods();
        for(Method m : methods){
            methodsString += "@Override "+ rt+
                    "public void "+m.getName()+" (){"+"" +rt+
                    "        long start = System.currentTimeMillis();"+rt+
                    "        System.out.println(\"start time is \"+start);"+rt+
                    "        t."+m.getName()+"();"+rt+
                    "        long end = System.currentTimeMillis();"+rt+
                    "        System.out.println(\"end time is \"+end);"+rt+
                    "        System.out.println(\"time is \"+(end - start));"+rt+
                    "}"+rt;
        }


        //将一下字符串动态编译,生成代理类
        //实现方式有以下击中:jdk6.0 complier API;CGLib;  ASM

        String src =
                "public class TankTimeProxy implements " +intf.getName()+ "{"+rt+   //直接用intf,是调用toString方法,前会加入字符串 interface
                        "    Moveable t;"+rt+

                        "    public TankTimeProxy("+intf.getName()+" t) {"+rt+
                        "    this.t = t;"+rt+
                        "    }"+rt+

                        methodsString+
                        "}";

        //进行编译
        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)
        //管理动态生成d文件
        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();
        //System.out.println("***************************************");

        //************以上过程获得了java文件源码,编译生成了java文件的class文件*******
        //加载至内存,生成新对象
        //Class.load(0 是加载path路径的class文件
        //URLClassLoader是将硬盘中的class文件加载进入

        //通过Url引入本地文件
        URL[] urls = new URL[]{new URL("file:/"+"g:/src/")}; //访问本地文件   指定class文件存放的位置
        //去指定路径寻找class文件
        URLClassLoader urlClassLoader = new URLClassLoader(urls);

        Class c = urlClassLoader.loadClass("TankTimeProxy");

        System.out.println(c);

        //执行
        //c.newInstance(); 是调用空的构造方法

        //获得构造方法
        //根据java虚拟机,每一个构造方法也相当于一个对象
        Constructor constructor = c.getConstructor(intf);

        //产生新对象
        Object m =  constructor.newInstance(new Tank());  //new Tank()为构造方法的参数   即被代理对象

        //m.move();

        return m;
    }
}

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

标签:

原文地址:http://www.cnblogs.com/chentao-cus/p/4817174.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!