java之Spring(AOP)前奏-動態代理設計模式(下)


在上一章我們看到了,新增的三種類都能實現對原始功能類進行添加功能的事務處理,這三種類就是一個代理。

但是這種代理是寫死的,怎樣實現對任意接口添加自定義的代理呢?

我們先來看一下之前的代理實現:

 1 public class Impeat {
 2     private InterfaceDo todo;
 3     public Impeat(InterfaceDo todo) {
 4         super();
 5         this.todo = todo;
 6     }
 7     public void dothings() {
 8         todo.dosomething();
 9         System.out.println("我要吃飯了啊--------");
10     }
11 }

因為這里我們的代理不需要再被其他代理引用,所以就不需要實現InterfaceDo接口,自然內部方法也是可以自定義,沒有必要

遵循InterfaceDo的方法定義,為了避免混淆,我們將其改為了dothings(),由於代理類都是這樣的一個書寫模式:定義成員變量、

構造函數為成員變量賦值為代理對象、自定義方法實現對代理對象方法的調用。我們索性定義一個接口,以后所有的代理類都按

照統一模式來寫,在JDK中就定義了這樣的一個接口InvocationHandler,我們的代理類都實現這個接口,遵循它的書寫方式,

下面我們再來看看代理類里面的元素:

InterfaceDo:需要代理對象的實現接口;

todo:需要代理的對象;

紅字:為代理對象添加的功能實現;

todo.dosomething():代理對象的原始功能。

既然要實現動態代理,那么這個代理實現的部分源碼,就不能寫死了(被代理對象的接口、被代理的對象以及被代理對象內部的

方法),接口我們可以自定義,被代理對象我們可以new出來,但是被代理對象內部的方法是不確定的,A代理對象可能是A方法,

B代理對象可能是B方法,C代理對象可能是C方法。

所以,我們要動態獲取代理對象的內部方法就得通過反射來獲得。

被代理對象的方法怎么獲得呢?由於被代理對象是實現了接口的,被代理對象的內部方法必定也是重寫自接口的定義方法的。那么

我們就可以從接口入手,獲取接口的方法定義。

來看看JDK的實現:

public class Handlerimp implements InvocationHandler {
    private Object obj;
    public Handlerimp(Object obj) {
        super();
        this.obj = obj;
    }
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("-----我要實現新的功能-----");
        Object returnValue = method.invoke(obj, args);
        return returnValue;
    }
}

是不是很眼熟,對,這個和我們之前的靜態代理實現模式一樣。只不過底層已經用反射幫我們獲得了被代理對象obj的方法method

以及方法的參數數組,然后通過被代理對象、方法、參數三者來執行被代理對象的方法-------method.invoke(proxy,args)。

接下來,我們實例化一個該代理類的實例:

public class Testperson {
    public static void main(String[] args) {
        InterfaceDo a = new Persontodo();
        Handlerimp handler =new Handlerimp(a);
        ClassLoader loader = a.getClass().getClassLoader();
        Class[] interfaces = a.getClass().getInterfaces();
        InterfaceDo subject = (InterfaceDo) Proxy.newProxyInstance(loader, interfaces, handler);
        subject.dosomething();
        subject.dothing();
    }
}

 

我們可以看到,JDK中通過Proxy類的靜態方法newProxyInstance()獲得代理類實例;

該方法實現了對被代理對象所有方法的遍歷,因此實現了對被代理對象所有方法的功能添加。

之后,我們就可以調用代理類的方法了。


免責聲明!

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



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