一、簡介
首先介紹下什么是代理,所謂代理就是當原有的類的方法不足以滿足我們的需求的時候,我們需要額外進行一些其他的操作的時候,為了盡量不改寫業務邏輯,我們不直接調用類本身,而是借助另一個包裝好了所有需求的方法的類來實現,當然,這個類里也可以調用原有類的方法,如果需要調用原有類的方法的話(大多數情況下)就需要讓該類持有原類的一個對象作為他的成員變量,以方便對原有類中方法的調用。那么這個類就可以稱之為代理類了,代理的工作流程如下:
代理本身又分為靜態代理和動態代理,這里的靜態和動態分別指的是什么呢,我們知道,要讓代理類執行原有類里的方法,我們得讓代理類持有原有類的對象,這就意味着,如果有多個類需要代理,我們就得寫多個代理類,這個是靜態代理,如果是動態代理的話,只需要一個代理類就可以搞定,因為動態代理類不需要持有原類的對象,他需要代理類實現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 說明:用來獲得一個代理對象
三、設計的結構
從上往下說吧:
- 首先所有准備被代理的類要各自有一個接口
- 可以有多個准備被代理的類,里面封裝好業務邏輯方法
- 要有一個實現了InvocationHandler的代理類,如果需要調用原有類的方法,在代理類中可以封裝一個Object類型的成員變量,必須要實現好invoke方法,封裝好需要代理的邏輯,可以通過調用method.invoke(object,args)的方法調用對應object對象的method方法,並傳入args參數,其中object對象就是我們上面說的成員變量。
- 通過Proxy.newProxyInstance方法獲取一個代理對象,需要傳入三個參數:被代理類的類加載器,被代理類的接口列表,代理類對象實例。
- 代理對象強轉成對應的接口類型,並調用接口里的方法,可以接收返回值。
注:代理對象和代理類對象實例不是一個事情哈,代理對象是通過Proxy.newProxyInstance獲取到的,可以強轉成接口類型的,代理類對象是指我們定義的實現InvocationHandler的類的對象實例。
四、調用方式
這里可能有點冗余,這里是從下往上說的:
- 通過Proxy.newProxyInstance方法獲取一個代理對象,需要傳入三個參數:被代理類的類加載器,被代理類的接口列表,代理類對象實例。
- 將這個代理對象強轉成對應的接口類型,並調用接口里的方法,可以接收返回值。
- 上一步操作將會自動跳用代理類里的invoke方法
- invoke方法里可以通過執行:method.invoke(object,args)調用object對象的method方法,並傳入args參數,可以接收返回值。這個object需要提前寫成Object類型的成員變量,在第一步需要代理類對象實例,可以在獲取實例的時候就把對應的類(被代理的類)生成的對象傳進去。
- 上一步中調用method方法會自動調用object對象里的method方法。
- 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();
