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

页面导航:首页 > 软件编程 > 其它相关 > 深度模拟java动态代理实现机制系类之二

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

来源:互联网 作者:脚本宝典 时间:2015-09-18 13:15 【

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

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

这里不一样的只有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;
    }
}


Tags:

文章评论

最 近 更 新
热 点 排 行
Js与CSS工具
代码转换工具

<