Android 中的動態(tài)代理
動態(tài)代理的優(yōu)點有:
- 隱藏委托類的實現(xiàn)
- 解耦壶唤,不改變委托類代碼情況下做一些額外處理
- 方便對代理類的函數(shù)做統(tǒng)一或特殊處理
實現(xiàn)步驟
-
新建接口類
public interface Subject { public void doSomething(); }
-
創(chuàng)建委托類并實現(xiàn)定義的接口類
public class RealSubject implements Subject { public void doSomething() { System.out.println( "call doSomething()" ); } }
-
創(chuàng)建代理幫助類,實現(xiàn)InvocationHandler接口
InvocationHandler:是負(fù)責(zé)連接代理類和委托類的中間類必須實現(xiàn)的接口
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyHandler implements InvocationHandler { private Object tar; //綁定委托對象晚凿,并返回代理類 public Object bind(Object tar) { //tar屬性表示委托類對象梆暖。 this.tar = tar; //綁定該類實現(xiàn)的所有接口,取得代理類 return Proxy.newProxyInstance( //loader表示類加載器 tar.getClass().getClassLoader(), //interfaces表示委托類的接口,生成代理類時需要實現(xiàn)這些接口 tar.getClass().getInterfaces(), //InvocationHandler實現(xiàn)類對象响蕴,負(fù)責(zé)連接代理類和委托類的中間類 this); } //當(dāng)proxy生成字節(jié)碼時 會調(diào)用invoke方法 public Object invoke(Object proxy , Method method , Object[] args)throws Throwable { Object result = null; //這里就可以進(jìn)行所謂的AOP編程了 //在調(diào)用具體函數(shù)方法前,執(zhí)行功能處理 result = method.invoke(tar,args); //在調(diào)用具體函數(shù)方法后惠桃,執(zhí)行功能處理 return result; } }
public class TestProxy { public static void main(String args[]) { ProxyHandler proxy = new ProxyHandler(); //綁定該類實現(xiàn)的所有接口 Subject sub = (Subject) proxy.bind(new RealSubject()); //調(diào)用代理對象的每個函數(shù)實際最終都是調(diào)用了InvocationHandler的invoke函數(shù)浦夷。 sub.doSomething(); } }
原理
動態(tài)代理可以理解為雙向靜態(tài)代理,我們先是創(chuàng)建委托類B辜王,系統(tǒng)動態(tài)生成代理類A劈狐。
然后創(chuàng)建一個實現(xiàn)了InvocationHandler的子類C,子類連接代理類A和委托類B呐馆。
它是代理類A的委托類肥缔,是委托類B的代理類。
用戶直接調(diào)用代理類A的對象汹来,A將調(diào)用轉(zhuǎn)給它的委托類C续膳,委托類C再將調(diào)用轉(zhuǎn)發(fā)給它的委托類B改艇。
用到的地方
- jfinal框架中的攔截器機(jī)制就是基于動態(tài)代理實現(xiàn)的。
- 使用 cglib 動態(tài)代理
- 將InvocationHandler抽象為一個Invocation坟岔,在invoke方法中實現(xiàn)調(diào)用委托類方法之前對本次請求進(jìn)行攔截谒兄。
- Retrofit:簡化了網(wǎng)絡(luò)請求