模擬實現JDK動態代理
阿新 • • 發佈:2019-02-18
要模擬動態代理實現必須引入一個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();
}
}