動態(tài)代理

代理的概念

為某個對象提供一個代理,以控制對這個對象的訪問。 代理類和委托類有共同的父類或父接口,這樣在任何使用委托類對象的地方都可以用代理對象替代。代理類負(fù)責(zé)請求的預(yù)處理、過濾、將請求分派給委托類處理、以及委托類執(zhí)行完請求后的后續(xù)處理。

動態(tài)代理

動態(tài)代理類的源碼是在程序運行期間由JVM根據(jù)反射等機制動態(tài)的生成,所以不存在代理類的字節(jié)碼文件。代理類和委托類的關(guān)系是在程序運行時確定。
在java的動態(tài)代理API中,有兩個重要的類和接口,一個是Proxy(Class)、另一個則是 InvocationHandler(Interface),這一個類和接口是實現(xiàn)我們動態(tài)代理所必須用到的

動態(tài)代理設(shè)計模式

![GWY96GFG]QC)IP45~}6__2.png

1、被代理類+增強=生成新的類(java)
2、編譯新的類(class)
3、加載新的類
4、創(chuàng)建代理對象$Proxy12 (12是隨機數(shù))

Proxy(Class)(一般我們用最后一種方法)

Proxy是 Java 動態(tài)代理機制的主類,它提供了一組靜態(tài)方法來為一組接口動態(tài)地生成代理類及其對象。
Proxy 的靜態(tài)方法

      static InvocationHandler getInvocationHandler(Object proxy)

該方法用于獲取指定代理對象所關(guān)聯(lián)的調(diào)用處理器

static Class getProxyClass(ClassLoader loader, Class[] interfaces)

該方法用于獲取關(guān)聯(lián)于指定類裝載器和一組接口的動態(tài)代理類的類對象

static boolean isProxyClass(Class cl)

該方法用于判斷指定類對象是否是一個動態(tài)代理類

static Object newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)

loader 指定代理類的ClassLoader加載器
interfaces 指定代理類要實現(xiàn)的接口
h: 表示的是當(dāng)我這個動態(tài)代理對象在調(diào)用方法的時候,會關(guān)聯(lián)到哪一個InvocationHandler對象上
該方法用于為指定類裝載器、一組接口及調(diào)用處理器生成動態(tài)代理類實例

InvocationHandler(Interface)

InvocationHandler是負(fù)責(zé)連接代理類和委托類的中間類必須實現(xiàn)的接口,它自定義了一個 invoke 方法,用于集中處理在動態(tài)代理類對象上的方法調(diào)用,通常在該方法中實現(xiàn)對委托類的代理訪問。

InvocationHandler 的核心方法

Object invoke(Object proxy, Method method, Object[] args)
proxy 該參數(shù)為代理類的實例
method 被調(diào)用的方法對象
args 調(diào)用method對象的方法參數(shù)
該方法也是InvocationHandler接口所定義的唯一的一個方法,該方法負(fù)責(zé)集中處理動態(tài)代理類上的所有方法的調(diào)用。調(diào)用處理器根據(jù)這三個參數(shù)進行預(yù)處理或分派到委托類實例上執(zhí)行。

動態(tài)代理的優(yōu)點和缺點

優(yōu)點

接口中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個集中的方法中處理(InvocationHandler.invoke)。這樣,在接口方法數(shù)量比較多的時候,我們可以進行靈活處理

缺點

它始終無法擺脫僅支持 interface 代理的桎梏,它們已經(jīng)注定有一個共同的父類叫 Proxy。Java 的繼承機制注定了這些動態(tài)代理類們無法實現(xiàn)對 class 的動態(tài)代理,原因是多繼承在 Java 中本質(zhì)上就行不通。

舉例

  public interface IDrink {
      public default void drink(){
          System.out.println("喝咖啡");
      }
  }


   public class Coffee implements IDrink{
         public void drink(){
           System.out.println("喝咖啡");
       }
   }


  public class MilkHandler implements InvocationHandler{
      Object obj=null;
      public MilkHandler(Object obj){
          this.obj=obj;
          }
      //proxy:被代理對象  method:需要被增強的方法  args:方法的參數(shù)
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          System.out.println("加牛奶");
          method.invoke(obj, args);//通過反射調(diào)用加牛奶的方法
          return null;
      }
  }


  public class Test {
      public static void main(String[] args) {
        Coffee c=new Coffee();//實現(xiàn)IDrink接口
          MilkHandler h=new MilkHandler(c);
          IDrink d=(IDrink)Proxy.newProxyInstance(c.getClass().getClassLoader(), c.getClass().getInterfaces(), h);//實現(xiàn)了IDrink接口
          d.drink();
      }
  }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文: Dyanmic Proxy Classes 介紹 一個動態(tài)代理類是實現(xiàn)了多個接口存在于運行時的類,這樣,一...
    半黑月缺閱讀 1,097評論 0 0
  • Java代理和動態(tài)代理機制分析和應(yīng)用 概述 代理是一種常用的設(shè)計模式,其目的就是為其他對象提供一個代理以控制對某個...
    丸_子閱讀 3,169評論 6 57
  • 1、代理概念 為某個對象提供一個代理,以控制對這個對象的訪問。 代理類和委托類有共同的父類或父接口,這樣在任何使用...
    孔垂云閱讀 7,959評論 4 54
  • 還是習(xí)慣北方的冬天,冷,有點干燥,太陽強烈而刺眼,有些冷風(fēng)會鉆進衣服,穿著厚厚的棉服悠閑地走在路上,甩甩帽子上的線...
    夜語聽鈴閱讀 272評論 0 2
  • 2017.6.9 對于“停在自己的陰影、獨自穿越沙漠的駱駝、渴望連結(jié)與看見、坦誠地去表達”,這些都是我最近一階段不...
    LOVE玲媛閱讀 801評論 0 0

友情鏈接更多精彩內(nèi)容