實現自己的動態代理,類似JDK動態代理
1,定義一個介面
public interface Person2 { public void findLove();
}
實現類
public class Zhangsan implements Person2{
private String name = "張三"; private String sex = "男"; public void findLove() { System.out.println("我的名字是:"+this.name+",我的性別是:"+this.sex); System.out.println("1,我要尋找的物件是白富美"); System.out.println("2,我的物件要有房有車"); }
}
2,實現自己的類載入器
public class ZLClassLoader extends ClassLoader{ /** * 重寫類的載入方式,將位元組碼載入到JVM中來 */ @Override protected Class<?> findClass(String name) throws ClassNotFoundException { //在URI中,包名及類名每一層中間都是用”/”來分隔的。
//在載入資源時,也是需要使用完整的類名,但是每層中間的”/”需要替換成”.”才行。
3,定義自己的ZLInvocationHandler 介面
public interface ZLInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
4,
public class ZLProxy { private static String ln = "\r\n";
/** * 生成代理類的例項 * * @param zlloader * @param interfaces * @param zlhandler * @return * @throws IllegalArgumentException */ public static Object newProxyInstance(ZLClassLoader zlloader, Class<?>[] interfaces, ZLInvocationHandler zlhandler) throws IllegalArgumentException { try { // 1動態生成java原始碼 String src = generateSrc(interfaces[0]); //輸出去看下是否語法編譯通過 String path = "D:/ws_sts/netty-test/target/classes/com/zl/test/custom/"; File srcfile = new File(path +"$Proxy0.java"); System.out.println(srcfile.getAbsolutePath()); FileWriter fw = new FileWriter(srcfile); fw.write(src); fw.flush(); fw.close(); // 2將生成的原始檔編譯為class位元組碼 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null); Iterable<? extends JavaFileObject> iter = standardFileManager.getJavaFileObjects(srcfile); CompilationTask task = compiler.getTask(null, standardFileManager, null, null, null, iter); task.call();//生成class 檔案 standardFileManager.close(); //刪除原始檔,實現無感知的動態生成檔案 srcfile.delete(); // 3將位元組碼載入到JVM Class<?> clz = zlloader.findClass("$Proxy0"); // 4反射生成代理物件 Constructor<?> c = clz.getConstructor(ZLInvocationHandler.class); return c.newInstance(zlhandler); } catch (Exception e) { e.printStackTrace(); } return null; }
/** * 動態生成原始碼 * * @return */ public static String generateSrc(Class<?> interfaces) { StringBuffer src = new StringBuffer(); src.append("package com.zl.test.custom;").append(ln); src.append("import java.lang.reflect.*;").append(ln).append(ln); src.append("public class $Proxy0 implements "+interfaces.getName()+"{"+ln); src.append("\t").append("private ZLInvocationHandler h;"+ln).append(ln); src.append("\t").append("public $Proxy0(ZLInvocationHandler h){"+ln); src.append("\t").append("\t").append("this.h=h;"+ln); src.append("\t").append("}"+ln).append(ln); //獲取目標類的方法 for(Method m :interfaces.getMethods()) { src.append("\t").append("public "+ m.getReturnType().getSimpleName() + " "+m.getName() +"(){").append(ln); src.append("\t").append("\t").append("try{").append(ln); src.append("\t").append("\t\t").append("Method mm = "+interfaces.getName()+".class.getMethod(\""+m.getName()+"\", new Class[]{});").append(ln); src.append("\t").append("\t\t").append("this.h.invoke(this, mm ,null);").append(ln); src.append("\t").append("\t").append("}catch(Throwable e){e.printStackTrace();}").append(ln); src.append("\t").append("\t").append("return;").append(ln); src.append("\t").append("}").append(ln); } src.append("}"+ln); return src.toString(); }
}
5,生成代理物件
public class CusMeiPo implements ZLInvocationHandler{
private Person2 target; /** * 生成一個代理物件 * @return */ public Object getInstance(Person2 target) { this.target = target; Class<?> clz = target.getClass(); System.out.println("被代理的物件是==》"+clz); return ZLProxy.newProxyInstance(new ZLClassLoader(), clz.getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("媒婆開始收費。。。。");
method.invoke(this.target, args); System.out.println("媒婆收費牽線任務完畢。。。。。"); return null; }
}
測試:
public class Test { public static void main(String[] args) { Person2 target = new Zhangsan(); Person2 proxy= (Person2) new CusMeiPo().getInstance(target); proxy.findLove(); }
}
測試結果: