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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

浅谈java代理

發(fā)布時(shí)間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈java代理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【0】README

0.1) 本文描述+源代碼均 轉(zhuǎn)自 core java volume 1, 旨在理解 java代理機(jī)制 的基礎(chǔ)知識(shí);


【1】代理相關(guān)

1.1)利用代理可以在運(yùn)行時(shí)創(chuàng)建一個(gè)實(shí)現(xiàn)了一組給定接口的新類, 這種功能只有在 編譯時(shí)無(wú)法確定需要實(shí)現(xiàn)哪個(gè)接口時(shí) 才有必要使用;
1.2)假設(shè)有一個(gè)表示接口的 Class對(duì)象, 它的確切類型在編譯時(shí)無(wú)法知道。 要想構(gòu)造一個(gè)實(shí)現(xiàn)這些接口的類, 就需要使用 newInstance 方法或反射找出這個(gè)類的構(gòu)造器;但是不能實(shí)例化一個(gè)接口, 需要在程序處于運(yùn)行狀態(tài)時(shí)定義一個(gè)新類;
1.3)解決問(wèn)題的方法(代理機(jī)制): 代理機(jī)制是一種更好的解決方法。代理類可以在運(yùn)行時(shí)創(chuàng)建全新的類, 這樣代理類能夠?qū)崿F(xiàn)指定的接口,尤其是, 它具有以下方法:

  • 1.3.1)指定接口所需要的全部方法;
  • 1.3.2) Object 類中的全部方法, 例如 , toString, equals等;
  • 1.3.3)然而,不能在運(yùn)行時(shí)定義這些方法的新代碼。而是要提供一個(gè) 調(diào)用處理器(InvocationHandler), 該處理器是實(shí)現(xiàn)了 InvocationHandler 接口的類對(duì)象。在這個(gè)接口中只有一個(gè)方法: Object invoke(Object proxy, Method method, Object[] args) ; 要知道, 無(wú)論何時(shí)調(diào)用代理對(duì)象的方法, 調(diào)用處理器的invoke 方法都會(huì)被調(diào)用, 并向其傳遞Method對(duì)象和原始的調(diào)用參數(shù);

1.4)要想創(chuàng)建一個(gè)代理對(duì)象, 需要使用Proxy類的 newProxyInstance 方法, 該方法有3個(gè)參數(shù):

  • 1.4.1)一個(gè)類加載器:
  • 1.4.2)一個(gè)Class 對(duì)象數(shù)組: 每個(gè)元素都是需要實(shí)現(xiàn)的接口;
  • 1.4.3)一個(gè)調(diào)用處理器:
class TraceHandler implements InvocationHandlerInvocationHandler handler = new TraceHandler(value); Object proxy = Proxy.newProxyInstance(null, new Class[] { Comparable.class } , handler);

1.5)但是,還有兩個(gè)問(wèn)題需要解決:
當(dāng)然了,這兩個(gè)問(wèn)題的答案取決于打算使用代理機(jī)制解決什么問(wèn)題。使用代理可能出于很多原因,如:

  • ex1)路由對(duì)遠(yuǎn)程服務(wù)費(fèi)去的方法調(diào)用;
  • ex2)在程序運(yùn)行期間, 將用戶接口事件與動(dòng)作關(guān)聯(lián)起來(lái);
  • ex3)為調(diào)試, 跟蹤方法調(diào)用;

【2】看個(gè)荔枝(跟蹤方法調(diào)用):

public class ProxyTest {public static void main(String[] args){Object[] elements = new Object[1000];// fill elements with proxies for the integers 1 ... 1000for (int i = 0; i < elements.length; i++){Integer value = i + 1;InvocationHandler handler = new TraceHandler(value);Object proxy = Proxy.newProxyInstance(null, new Class[] { Comparable.class } , handler);elements[i] = proxy;}// construct a random integerInteger key = new Random().nextInt(elements.length) + 1;// search for the keyint result = Arrays.binarySearch(elements, key);// print match if foundif (result >= 0) System.out.println(elements[result]);} }class TraceHandler implements InvocationHandler {private Object target;public TraceHandler(Object t){target = t;}public Object invoke(Object proxy, Method m, Object[] args) throws Throwable{// print implicit argumentSystem.out.print(target);// print method nameSystem.out.print("." + m.getName() + "(");// print explicit argumentsif (args != null){for (int i = 0; i < args.length; i++){System.out.print(args[i]);if (i < args.length - 1) System.out.print(", ");}}System.out.println(")");// invoke actual methodreturn m.invoke(target, args);} }

2.1)打印結(jié)果:

【2】代理類的特性

2.1)需要記住: 代理類是在程序運(yùn)行過(guò)程中創(chuàng)建的, 然而, 一旦被創(chuàng)建, 就變成了常規(guī)類,與虛擬機(jī)中的任何其他類沒(méi)有區(qū)別;
2.2)所有的代理類都擴(kuò)展于 Proxy類。一個(gè)代理類只有一個(gè)實(shí)例域——調(diào)用處理器, 它定義在 Proxy的超類中, 為了履行代理對(duì)象的職責(zé), 所需要的任何附加數(shù)據(jù)都必須存儲(chǔ)在調(diào)用處理器中;
2.3)所有的代理類都覆蓋了 Object類中的方法 toString、equals 和 hashCode 方法;這些方法僅僅 調(diào)用了 調(diào)用處理器 的invoke 方法;Object類中的其他方法沒(méi)有被重新定義;
2.4)沒(méi)有定義代理類的名字的話, Sun 虛擬機(jī)中的Proxy類將生成一個(gè) 以 字符串 $Proxy 開(kāi)頭的類名;
2.5)對(duì)于特定的類加載器和預(yù)設(shè)的一組接口來(lái)說(shuō), 只能有一個(gè)代理類;也就是說(shuō), 如果使用 同一個(gè)類加載器和接口數(shù)組調(diào)用兩次 newProxyInstance 方法的話, 那么只能夠得到同一個(gè)類的兩個(gè)對(duì)象, 也可以利用 getProxyClass 方法獲得這個(gè)類:

Class proxyClass = Proxy.getProxyClass(null, interfaces);

2.6)代理類一定是 public 和 final, 如果代理類實(shí)現(xiàn)的所有接口都是 public, 代理類就不屬于某個(gè)特定的包;否則,所有非公有的接口都必須屬于同一個(gè)包;
2.7)可以調(diào)用 Proxy類中的 isProxyClass 方法 檢測(cè)一個(gè)特定的 Class對(duì)象是否代表一個(gè)代理類;

[API] java.lang,reflect.InvocationHandler 1.3

Object invoke(Object proxy, Method method, Object[] args):返回實(shí)現(xiàn)指定接口的代理類; static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler handler) : 構(gòu)造一個(gè)實(shí)現(xiàn)指定接口的代理類的實(shí)例, 所有方法都將調(diào)用給定處理器對(duì)象的invoke 方法; static boolean isProxyClass(Class c) : 如果 c 是一個(gè)代理類返回 true

總結(jié)

以上是生活随笔為你收集整理的浅谈java代理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。