模拟实现JDK动态代理

来源:互联网 发布:入门耳机 知乎 编辑:程序博客网 时间:2024/05/22 06:20

要模拟动态代理实现必须引入一个commons-io 包 用于创建java文件

首先我们创建一个被代理类:car 车辆

package com.zs.spring.demo2;import java.util.Random;public class Car implements Moveable {    @Override    public void move() {        //实现开车        try {            Thread.sleep(new Random().nextInt(1000));            System.out.println("汽车行驶中....");        } catch (InterruptedException e) {            e.printStackTrace();        }    }}

创建一个行驶的接口类

package com.zs.spring.demo2;public interface Moveable {    public void move() ;}

//创建一个事务代理类接口

package com.zs.spring.demo2;import java.lang.reflect.Method;public interface InvocationHandler {    public void invoke(Object o,Method m);}

创建一个记录行驶时间的事务处理器实现 InvocationHandler 接口

package com.zs.spring.demo2;import java.lang.reflect.Method;public class TimeHandler implements  InvocationHandler{    private Object target;    public TimeHandler(Object target) {        super();        this.target = target;    }    @Override    public void invoke(Object o, Method m) {        try {            long starttime = System.currentTimeMillis();            System.out.println("汽车开始行驶....");            m.invoke(target);            long endtime = System.currentTimeMillis();            System.out.println("汽车结束行驶....  汽车行驶时间:"                            + (endtime - starttime) + "毫秒!");        } catch (Exception e) {            e.printStackTrace();        }    }}

创建动态代理类

package com.zs.spring.demo2;import java.io.File;import java.lang.reflect.Constructor;import java.lang.reflect.Method;import javax.tools.JavaCompiler;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;import javax.tools.JavaCompiler.CompilationTask;import org.apache.commons.io.FileUtils;public class Proxy {    @SuppressWarnings("unchecked")    public static Object newProxyInstance(Class infce,InvocationHandler h) throws Exception{        String rt = "\r\n";        String methodStr = "";        for(Method m : infce.getMethods()){            methodStr += "  @Override" + rt +            "   public void " + m.getName() + "() {" + rt +            "  try{" + rt +            "  Method md = " + infce.getName() + ".class.getMethod(\""                                         + m.getName() + "\");" + rt +            "  h.invoke(this,md);" +rt+             "  }catch(Exception e){ e.printStackTrace();}" + rt +            "   }" ;        }        String str =        "package com.zs.spring.demo2;" + rt +        "import java.lang.reflect.Method;" + rt +        "import com.zs.spring.demo2.InvocationHandler;" +  rt+        "public class $Proxy0 implements " + infce.getName() + " {" + rt +        "   public $Proxy0(InvocationHandler h) {" + rt +        "       this.h = h;" + rt +        "   }" + rt +        "  private InvocationHandler h;" + rt+         methodStr + rt +        "}" ;        //产生代理类的java文件        String filename = System.getProperty("user.dir") +"/bin/com/zs/spring/demo2/$Proxy0.java";        File file = new File(filename);        FileUtils.writeStringToFile(file, str);        //编译        //拿到编译器        JavaCompiler complier = ToolProvider.getSystemJavaCompiler();        //文件管理者        StandardJavaFileManager fileMgr =                 complier.getStandardFileManager(null, null, null);        //获取文件        Iterable units = fileMgr.getJavaFileObjects(filename);        //编译任务        CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units);        //进行编译        t.call();        fileMgr.close();        //load 到内存        ClassLoader cl = ClassLoader.getSystemClassLoader();        Class c = cl.loadClass("com.zs.spring.demo2.$Proxy0");        Constructor ctr = c.getConstructor(InvocationHandler.class);        return ctr.newInstance(h);    }}

创建我们的测试类

package com.zs.spring.demo2;public class Test { public static void main(String[] args) throws Exception {        Car car = new Car();        InvocationHandler h = new TimeHandler(car);        Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class,h);        m.move();}}
原创粉丝点击