日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深度模拟java动态代理实现机制系类之三

發布時間:2024/4/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深度模拟java动态代理实现机制系类之三 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這里的內容就比較復雜了,要實現的是對任意的接口,對任意指定的方法,以及對任意指定的代理類型進行代理,就更真實的模擬出java虛擬機的動態代理機制

羅列一下這里涉及的類、接口之間的關系,方便大家學習。
1、InvocationHandler接口,用來處理指定的方法,即對特定方法的代理,處理的具體實現交由子類實現
2、TimeHandler類,實現了InvocationHandler接口的子類,具體的代理實現是進行時間代理
3、Proxy類,用于產生代理類的類
4、Moveable接口,舉例過程中各類要實現的統一接口
5、Tank類,實現了Moveable接口,即被代理的類
6、Cilent,操作客戶端

先把整個的思路理一下:
首先在Client端,new一個被代理的對象Tank,Tank對象作為構造參數傳入代理處理類TimeHandler,new出一個TimeHandler對象,
Tank的接口Moveable和TimeHandler對象作為參數傳入Proxy,Proxy調用newProxyInstance方法,該方法中對接口的所有的方法,利用TimeHandler對象進行代理,(可以簡單理解為將接口方法與TimeHandler代理方法結合),生成新的代理對象的java文件、class文件、然后加載進入內存,利用反射獲得一個代理對象,返回該代理對象,在Client端調用則調用了代理對象方法;


1、InvocationHandler接口

1 package com.csu.proxy; 2 3 import java.lang.reflect.Method; 4 //對任意方法自定義處理 5 //方法調用的處理器 6 public interface InvocationHandler { //定義一個接口,用來處理方法,處理的具體實現交由子類實現 7 8 public void invoke(Object o, Method m); //對某個指定方法的處理 9 }

?



2、TimeHandler類

1 package com.csu.proxy; 2 3 import java.lang.reflect.Method; 4 public class TimeHandler implements InvocationHandler { 5 private Object target;//被代理的對象 6 7 public Object getT() { 8 return target; 9 } 10 11 public void setT(Object t) { 12 this.target = t; 13 } 14 15 public TimeHandler(Object target) { 16 this.target = target; 17 } 18 19 @Override 20 public void invoke(Object o,Method m){ //必須指定具體對象對具體的方法的調用 21 long start = System.currentTimeMillis(); 22 System.out.println("start time is " + start); 23 System.out.println(o.getClass().getName()); 24 //m 調用方法 25 try { 26 m.invoke(target); 27 } catch (Exception e) {e.printStackTrace();} 28 29 30 long end = System.currentTimeMillis(); 31 System.out.println("end time is "+end); 32 System.out.println("time is "+(end - start)); 33 } 34 }

?


3、Moveable接口

1 package com.csu.proxy; 2 3 public interface Moveable { 4 void move(); 5 }

?



4、Tank類

1 package com.csu.proxy; 2 3 import java.util.Random; 4 5 6 public class Tank implements Moveable { 7 8 @Override 9 public void move() { 10 11 System.out.println("Tank Moving..."); 12 try { 13 Thread.sleep(new Random().nextInt(10000)); 14 } catch (InterruptedException e) { 15 e.printStackTrace(); 16 } 17 18 } 19 20 }

?



5、Proxy類

1 package com.csu.proxy; 2 3 import javax.tools.JavaCompiler; 4 import javax.tools.StandardJavaFileManager; 5 import javax.tools.ToolProvider; 6 import java.io.File; 7 import java.io.FileWriter; 8 import java.lang.reflect.Constructor; 9 import java.lang.reflect.Method; 10 import java.net.URL; 11 import java.net.URLClassLoader; 12 13 /** 14 方便大家閱讀,關注主要的邏輯思路,將在前面博客的已經寫過的注釋代碼清除,因為這是一系列,有很多代碼引用 15 有想要看的,去上幾篇文章看吧 16 **/ 17 18 //該類要實現對任意接口,任意方法,以及任意的代理 的實現 19 public class ProxyG3 { 20 public static Object newProxyInstance(Class intf, InvocationHandler h) throws Exception{ 21 //invocationHandler當成參數,指定代理的類型,即指定對方法要進行什么處理 22 23 //*****************1、獲得java文件********************************** 24 String methodsString = ""; 25 String rt = "\r\n"; 26 27 Method[] methods = intf.getMethods(); 28 for(Method m : methods) { 29 methodsString += "@Override" + rt + 30 "public void " + m.getName() + "() {" + rt + 31 " try {" + rt + 32 " Method md = " + intf.getName() + ".class.getMethod(\"" + m.getName() + "\");" + rt + 33 " h.invoke(this, md);" + rt + 34 " }catch(Exception e) {e.printStackTrace();}" + rt + 35 36 "}"; 37 } 38 39 String src = 40 "package com.csu.proxy;" + rt + 41 "import java.lang.reflect.Method;" + rt + 42 "public class TankTimeProxy implements " + intf.getName() + "{" + rt + 43 " public TankTimeProxy(InvocationHandler h) {" + rt + 44 " this.h = h;" + rt + 45 " }" + rt + 46 47 48 " com.csu.proxy.InvocationHandler h;" + rt + 49 50 methodsString + 51 "}"; 52 String fileName = "g:/src/com/csu/proxy/TankTimeProxy.java";//放在指定的地方 53 File f = new File(fileName); 54 FileWriter fw = new FileWriter(f); 55 fw.write(src); 56 fw.flush(); 57 fw.close(); 58 /** 59 這里重點說一下:用于存放代理對象TankTimeProxy的java和class文件的包名要工程中的其他java文件的包名一致,查看代碼你會發現 60 工程的java文件和生成的代理對象的java文件的包名都是 com.csu.proxy; 61 **/ 62 63 //****************2、獲得class文件**************************************** 64 65  //獲得編譯器對象 66 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 67 68 //管理動態生成的文件 69 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null,null,null); 70 Iterable units = fileManager.getJavaFileObjects(fileName); 71 72 //“編譯任務”對象 73 JavaCompiler.CompilationTask task = compiler.getTask(null,fileManager,null,null,null,units); 74 task.call(); 75 fileManager.close(); 76 77 //*****************3、加載至內存****************************************** 78 79 //通過Url引入本地文件 80 URL[] urls = new URL[]{new URL("file:/"+"g:/src/")}; //訪問本地文件 指定class文件存放的位置 81 URLClassLoader urlClassLoader = new URLClassLoader(urls); 82 Class c = urlClassLoader.loadClass("com.csu.proxy.TankTimeProxy"); 83 84 //******************4、執行class文件,返回代理對象*************************************** 85 86 //獲得構造方法 87 Constructor constructor = c.getConstructor(InvocationHandler.class); //getConstructor的參數為Class類型,是原構造方法的參數的Class類型 88 89 //產生新對象 90 Object m = constructor.newInstance(h); 91 92 return m; 93 } 94 } 95 96 6、Cilent客戶端 97 98 package com.csu.proxy; 99 100 public class Client { 101 public static void main(String[] args) throws Exception { 102 103 Tank t = new Tank(); 104 InvocationHandler h = new TimeHandler(t); 105 106 Moveable m =(Moveable) ProxyG3.newProxyInstance(Moveable.class, h); 107 108 m.move(); 109 110 111 } 112 }

?

?

7、執行結果

(1)生成的java和class文件

(2)查看生成的java文件代碼

(3)運行結果

?

轉載于:https://www.cnblogs.com/chentao-cus/p/4817584.html

總結

以上是生活随笔為你收集整理的深度模拟java动态代理实现机制系类之三的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。