java動態代理

動態代理

1,動態代理的定義
顧名思義,動態代理既是起到動態的生成代理類的作用。代理類在程序運行時創建的代理方式被成為 動態代理。也就是說,這種情況下,代理類并不是在Java代碼中定義的,而是在運行時根據我們在Java代碼中的“指示”動態生成的。

2,動態代理的使用

(1)InvocationHandler接口在使用動態代理時,我們需要定義一個位于代理類與委托類之間的中介類,這個中介類被要求實現InvocationHandler接口,這個接口的定義如下:

1 public interface InvocationHandler {
2 
3 Object invoke(Object proxy, Method method, Object[] args);
4 
5 }

從InvocationHandler這個名稱我們就可以知道,實現了這個接口的中介類用做“調用處理器”。當我們調用代理類對象的方法時,這個“調用”會轉送到invoke方法中,代理類對象作為proxy參數傳入,參數method標識了我們具體調用的是代理類的哪個方法,args為這個方法的參數。這樣一來,我們對代理類中的所有方法的調用都會變為對invoke的調用,這樣我們可以在invoke方法中添加統一的處理邏輯(也可以根據method參數對不同的代理類方法做不同的處理)。因此我們只需在中介類的invoke方法實現中輸出“before”,然后調用委托類的invoke方法,再輸出“after”。下面我們來一步一步具體實現它。

(2)委托類的定義動態代理方式下,要求委托類必須實現某個接口,這里我們實現的是Sell接口。委托類Vendor類的定義如下:

 1  public class Vendor implements Sell {
 2 
 3   public void sell() {
 4
 5     System.out.println("In sell method");
 6
 7   }
 8
 9    public void ad() {
10
11     System,out.println("ad method")
12
13   }
14
15 }

(3)中介類上面我們提到過,中介類必須實現InvocationHandler接口,作為調用處理器”攔截“對代理類方法的調用。中介類的定義如下:

 1   public class DynamicProxy implements InvocationHandler {
 2
 3   private Object obj;
 4   //obj為委托類對象;
 5
 6   public DynamicProxy(Object obj) {
 7  
 8   this.obj = obj;
 9
10 }
11
12 
13  @Override
14   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
15
16      System.out.println("before");
17 
18      Object result = method.invoke(obj, args);
19 
20      System.out.println("after");
21 
22      return result;
23   }
24
25 }

從以上代碼中我們可以看到,中介類持有一個委托類對象引用,在invoke方法中調用了委托類對象的相應方法(第11行),看到這里是不是覺得似曾相識?通過聚合方式持有委托類對象引用,把外部對invoke的調用最終都轉為對委托類對象的調用。這不就是我們上面介紹的靜態代理的一種實現方式嗎?實際上,中介類與委托類構成了靜態代理關系,在這個關系中,中介類是代理類,委托類就是委托類; 代理類與中介類也構成一個靜態代理關系,在這個關系中,中介類是委托類,代理類是代理類。也就是說,動態代理關系由兩組靜態代理關系組成,這就是動態代理的原理。下面我們來介紹一下如何”指示“以動態生成代理類。

(4)動態生成代理類動態生成代理類的相關代碼如下:

1   public class Main {
2
3   public static void main(String[] args) {
4   //創建中介類實例
5
6      DynamicProxy inter =new DynamicProxy(new Vendor());
7
8    //加上這句將會產生一個$Proxy0.class文件,這個文件即為動態生成的代理類文件
9
10     System.getProperties().put( "sun.misc.ProxyGenerator.saveGeneratedFiles","true");
11   //獲取代理類實例sell
12
13     Sell sell = (Sell)(Proxy.newProxyInstance(Sell.class.getClassLoader(),
new Class[] {Sell.class}, inter));
14
15     //通過代理類對象調用代理類方法,實際上會轉到invoke方法調用
16
17     sell.sell();
18  
19     sell.ad();
20
21   }
22
23 }
24
25

在以上代碼中,我們調用Proxy類的newProxyInstance方法來獲取一個代理類實例。這個代理類實現了我們指定的接口并且會把方法調用分發到指定的調用處理器。這個方法的聲明如下:
復制代碼代碼如下:

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,   

InvocationHandler h) throws IllegalArgumentException

方法的三個參數含義分別如下:
loader:定義了代理類的ClassLoder;
interfaces:代理類實現的接口列表
h:調用處理器,也就是我們上面定義的實現了InvocationHandler接口的類實例
3,動態代理的優缺點

優點:Java動態代理可以避免靜態代理帶來的代碼冗余的問題。

缺點:Java動態代理只能針對接口創建代理,不能針對類創建代理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 前言 本文是我在學習代理模式時的一篇筆記,除了對代理模式、靜態和動態代理的概念和實現進行了描述外,還有關于動態代理...
  • 相關概念1.1 代理??在某些情況下,我們不希望或是不能直接訪問對象 A,而是通過訪問一個中介對象 B,由 B 去...
    天空在微笑閱讀 440評論 0 0
  • Java動態代理 引言 最近在看AOP代碼,其中利用到了Java動態代理機制來實現AOP織入。所以好好地把Java...
    草捏子閱讀 1,547評論 0 18
  • 之前介紹的反射和注解都是Java中的動態特性,還有即將介紹的動態代理也是Java中的一個動態特性。這些動態特性使得...
    Single_YAM閱讀 2,063評論 0 9
  • 那天的撞見,微涼的晨曦和鳥鳴的翠麗,走在公園的青石板,恰逢一樹一樹的花開。在目光的清落中,那猩紅的花蕊像醉了...
    三色堇的堇閱讀 169評論 0 1