動態代理的使用方式


一、簡介
    首先介紹下什么是代理,所謂代理就是當原有的類的方法不足以滿足我們的需求的時候,我們需要額外進行一些其他的操作的時候,為了盡量不改寫業務邏輯,我們不直接調用類本身,而是借助另一個包裝好了所有需求的方法的類來實現,當然,這個類里也可以調用原有類的方法,如果需要調用原有類的方法的話(大多數情況下)就需要讓該類持有原類的一個對象作為他的成員變量,以方便對原有類中方法的調用。那么這個類就可以稱之為代理類了,代理的工作流程如下:
    代理本身又分為靜態代理和動態代理,這里的靜態和動態分別指的是什么呢,我們知道,要讓代理類執行原有類里的方法,我們得讓代理類持有原有類的對象,這就意味着,如果有多個類需要代理,我們就得寫多個代理類,這個是靜態代理,如果是動態代理的話,只需要一個代理類就可以搞定,因為動態代理類不需要持有原類的對象,他需要代理類實現InvocationHandler接口,這個接口有一個需要實現的方法:public object invoke(Object proxy, Method method, Object[] args);這個方法里面我們要寫的就是動態調用的業務邏輯了,可以調用method.invoke(proxy,args)來調用proxy對象對應的method方法,傳入args參數,並返回object返回值,那問題來了,這個invoke函數是誰調用的呢,這個invoke函數其實是由代理對象調用接口里的方法動態調用的,換句話說,代理對象定義為接口類型的,當他調用接口里的方法的時候,並不是調用實現類里的方法,而是轉頭調用了這個invoke的方法,那問題又來了,如何獲取代理對象呢,可以通過Proxy.newProxyInstance方法獲取,將其返回類型強轉成對應的接口類型,就可以調用接口里的方法了。返回類型不能轉成實現類的類型,不然會報錯,報一個類轉換錯誤。
 
二、涉及到的類
InvocationHandler    說明:這是一個接口,代理類實現這個接口,然后實現接口中的invoke方法,作為回調使用的方法。
Proxy    說明:用來獲得一個代理對象
 
三、設計的結構
從上往下說吧:
  1. 首先所有准備被代理的類要各自有一個接口
  1. 可以有多個准備被代理的類,里面封裝好業務邏輯方法
  2. 要有一個實現了InvocationHandler的代理類,如果需要調用原有類的方法,在代理類中可以封裝一個Object類型的成員變量,必須要實現好invoke方法,封裝好需要代理的邏輯,可以通過調用method.invoke(object,args)的方法調用對應object對象的method方法,並傳入args參數,其中object對象就是我們上面說的成員變量。
  3. 通過Proxy.newProxyInstance方法獲取一個代理對象,需要傳入三個參數:被代理類的類加載器,被代理類的接口列表,代理類對象實例。
  4. 代理對象強轉成對應的接口類型,並調用接口里的方法,可以接收返回值。
 
注:代理對象和代理類對象實例不是一個事情哈,代理對象是通過Proxy.newProxyInstance獲取到的,可以強轉成接口類型的,代理類對象是指我們定義的實現InvocationHandler的類的對象實例。
 
四、調用方式
這里可能有點冗余,這里是從下往上說的:
  1. 通過Proxy.newProxyInstance方法獲取一個代理對象,需要傳入三個參數:被代理類的類加載器,被代理類的接口列表,代理類對象實例。
  2. 將這個代理對象強轉成對應的接口類型,並調用接口里的方法,可以接收返回值。
  3. 上一步操作將會自動跳用代理類里的invoke方法
  4. invoke方法里可以通過執行:method.invoke(object,args)調用object對象的method方法,並傳入args參數,可以接收返回值。這個object需要提前寫成Object類型的成員變量,在第一步需要代理類對象實例,可以在獲取實例的時候就把對應的類(被代理的類)生成的對象傳進去。
  5. 上一步中調用method方法會自動調用object對象里的method方法。
  6. object對象對應的類(被代理的類)需要繼承接口,因為第一步的時候就要拿到對應被代理類的接口列表。
 
五、范例代碼
接口:
1 package goods;
2  
3 public interface Healthy_drink {
4     void sell();
5     int getMoney();
6 }
 
被代理的類:
 1 package goods;
 2  
 3 public class Water implements Healthy_drink{
 4     private int money;
 5  
 6     public Water(){
 7  
 8     }
 9  
10     public Water(int money){
11         this.money = money;
12     }
13  
14     @Override
15     public int getMoney(){
16         return this.money;
17     }
18  
19     @Override
20     public void sell() {
21         System.out.println("water has selled by " + this.money);
22     }
23 }
 
代理類:
 1 package proxy;
 2  
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5  
 6 public class Dynamic_proxy implements InvocationHandler {
 7     private Object object;
 8  
 9     public Dynamic_proxy(){
10  
11     }
12  
13     public Dynamic_proxy(Object object){
14         this.object = object;
15     }
16  
17     @Override
18     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
19         System.out.println("through dynamic proxy");
20         System.out.println(proxy.getClass().getName());
21         Object result = method.invoke(object, args);
22         return result;
23     }
24 }
 
調用:
1 Water water = new Water(10);
2 Dynamic_proxy dynamic_proxy;
3 int money;
4 dynamic_proxy = new Dynamic_proxy(water);
5 Healthy_drink water_proxy = (Healthy_drink) Proxy.newProxyInstance(Water.class.getClassLoader(), Water.class.getInterfaces(), dynamic_proxy);
6 money = water_proxy.getMoney();
7 System.out.println("water value is " + money);
8 water_proxy.sell();
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM