1. 程式人生 > >實現自己的動態代理,類似JDK動態代理

實現自己的動態代理,類似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中,包名及類名每一層中間都是用”/”來分隔的。

       //在載入資源時,也是需要使用完整的類名,但是每層中間的”/”需要替換成”.”才行。

        String basePath = "D:/ws_sts/netty-test/target/classes/com/zl/test/custom/"+name+".class";                  File classFile = new File(basePath);                  if(classFile.exists()) {             FileInputStream fis = null;             ByteArrayOutputStream bos = null;             try {                 fis = new FileInputStream(classFile);                 bos = new ByteArrayOutputStream();                                  byte[] buff = new byte[1024];                 int len =0;                 while((len = fis.read(buff))!=-1) {                     bos.write(buff, 0, len);                 }                                  String className = ZLClassLoader.class.getPackage().getName()+"."+name;                 System.out.println("className===>"+className);                 //JVM讀取位元組碼
                Class<?> clz = defineClass(className, bos.toByteArray(), 0, bos.size());                                  System.out.println("載入檔案到JVM完畢。。。。");                                  //刪除位元組碼檔案,無感知                 classFile.delete();                                  return clz;             } catch (Exception e) {                 e.printStackTrace();             }finally {                 if(fis!=null) {                     try {                         fis.close();                     } catch (IOException e) {                         e.printStackTrace();                     }                 }                                  if(bos!=null) {                     try {                         bos.close();                     } catch (IOException e) {                         e.printStackTrace();                     }                 }             }         }         return null;     } }

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();     }

}

測試結果: