1. 程式人生 > >模擬實現JDK動態代理

模擬實現JDK動態代理

要模擬動態代理實現必須引入一個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();

}

}