動(dòng)態(tài)代理

動(dòng)態(tài)代理是代理模式的補(bǔ)充,傳統(tǒng)的代理模式要求我們?yōu)榇眍悇?chuàng)建class文件(.java文件編譯后的字節(jié)流),相對(duì)麻煩,動(dòng)態(tài)代理可以省去這個(gè)步驟,在運(yùn)行時(shí)生成和class文件等價(jià)的字節(jié)流,然后加載到JVM中。本文參考了http://www.lxweimin.com/p/6f6bb2f0ece9# ,在他之上增加了類圖和自己的理解。

老規(guī)矩,向上一張類圖。

類圖

DynamicProxy.png

實(shí)例

public class Main {

    public static void main(String args[]) {
        Subject realSubject = new RealSubject();  //創(chuàng)建委托對(duì)象
        ProxyHandler proxyHandler = new ProxyHandler(realSubject);  //創(chuàng)建InvocationHandler對(duì)象
        Subject proxy = (Subject)      Proxy.newProxyInstance(realSubject.getClass().getClassLoader()
                , realSubject.getClass().getInterfaces()
                , proxyHandler);  //生成代理對(duì)象
        
        proxy.request();   //使用代理對(duì)象
    }
}

interface Subject {
    public void request();
}

class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("real request");
    }
    
}

class ProxyHandler implements InvocationHandler{
    private Subject subject;
    public ProxyHandler(Subject subject){
        this.subject = subject;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) //proxy就是生成的代理對(duì)象
            throws Throwable {
        System.out.println("====before====");  //定義預(yù)處理的工作,當(dāng)然你也可以根據(jù) method的不同進(jìn)行不同的預(yù)處理工作
        Object result = method.invoke(subject, args);
        System.out.println("====after====");
        return result;
    }
}
------------------------------輸出---------------------------------------
====before====
real request
====after====

結(jié)合類圖,我們首先創(chuàng)建一個(gè)RealSubject對(duì)象,一個(gè)ProxyHandler對(duì)象,這個(gè)對(duì)象的類繼承自InvocationHandler,invoke(Object proxy, Method method, Object[] args)第一個(gè)參數(shù)proxy就是由反射創(chuàng)建的代理對(duì)象,第二參數(shù)表明代理對(duì)象調(diào)用的方法,第三個(gè)參數(shù)表示調(diào)用的參數(shù),在這個(gè)方法里我們調(diào)用了realSubject的對(duì)應(yīng)的方法,在之前和之后我們都可以做相應(yīng)的操作,這正是代理的含義。那個(gè)這個(gè)invoke(Object proxy, Method method, Object[] args)是什么時(shí)候調(diào)用的?答案是proxy.request();這個(gè)方法是自動(dòng)生成的,內(nèi)部實(shí)現(xiàn)類似

public final class $Proxy1 extends Proxy implements Subject{
   private InvocationHandler h;
   private $Proxy1(){}
   public $Proxy1(InvocationHandler h){
       this.h = h;
   }
   public int request(int i){
       Method method = Subject.class.getMethod("request", new Class[]{int.class});    //創(chuàng)建method對(duì)象
       return (Integer)h.invoke(this, method, new Object[]{new Integer(i)}); //調(diào)用了invoke方法
   }
}

這個(gè)方法將代理對(duì)象作為參數(shù)傳遞給InvocationHandler.invoke方法。所以調(diào)用鏈如下:proxy.request()--->InvocationHandler.invoke()。再結(jié)合類圖就不難理解。

參考

http://www.lxweimin.com/p/6f6bb2f0ece9#

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容