Java代理筆記

來源:互聯網
上載者:User

標籤:oca   err   ext   實現   color   min   system   style   靜態   

代理顧名思義,就是一個中介層,當我們要使用某個方法時,不直接調用,而是告訴代理,讓代理替我們去要求方法,並返回結果。在這個過程中,我們只知道代理執行並返回給了我們操作結果,至於它有沒有其他動作並不知道,但這個也無關緊要,因為不管代理在請求實際方法之前和之後做了什麼,對我們都不會產生任何影響。由於代理的這個特性,可以用來進行記錄日誌等操作。

代理分為靜態代理動態代理

靜態代理

靜態代理需要我們在調用者和具體的執行者之間建立一個代理類,其實現需要被代理的介面並持有一個此介面,具體代碼如下:

介面類(被代理):

public interface Hello {    void say(String name);}

代理類:

public class HelloProxy implements Hello {?    private Hello helloImpl;?    public HelloProxy() {        this.helloImpl = new HelloImpl(); // HelloImpl為一個Hello介面的一個普通實作類別    }?    @Override    public void say(String name) {        System.out.println("before say");        helloImpl.say(name);        System.out.println("after say");    }}

使用的時候只需要new一個代理類賦值給介面即可:Hello hello = new HelloProxy(),之後的執行會由代理類去負責。但是這麼做有一個問題就是對每個需要代理的類,都需要建立一個對應的代理類,即使代理類的邏輯都是相似的,動態代理就是解決這個問題的。

動態代理

動態代理相當於在調用者和代理類之間又增加了一個中介層,在這個中介層中完成代理類的邏輯,達到複用代碼的效果。這個中介層需要實現InvocationHandler介面,並持有一個被代理的類,大致代碼如下:

public class Myproxy implements InvocationHandler {?    private Object target; // 被代理的類?    public Myproxy(Object target) {        this.target = target;    }?    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("before invoke"); // 執行代理的方法前進行的操作        Object invoke = method.invoke(target, args); // 調用執行被代理的方法        System.out.println("after invoke"); // 執行代理的方法後進行的操作        return invoke; // 返回方法執行結果    }}

使用時,使用Proxy的靜態方法擷取代理類,將其強轉為對應的介面,之後可以同靜態代理類同樣使用。

Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

其中loader為類載入器,interfaces為要代理的介面,h為之前定義的實現InvocationHandler介面的類的執行個體。

這個方法會返回一個代理類,其實現的要代理的介面,並持有一個實現InvocationHandler介面的執行個體,代理類的代碼大致如下:

public final class $Proxy0 extends Proxy  implements Hello{?  public $Proxy0(InvocationHandler paramInvocationHandler) {    super(paramInvocationHandler);  }?  public final String say() {    try    {      return ((String)this.h.invoke(this, m3, null));    }    catch (RuntimeException localRuntimeException)    {      throw localRuntimeException;    }    catch (Throwable localThrowable)    {      throw new UndeclaredThrowableException(localThrowable);    }  }?}

如上代碼我們可以將其強轉為Hello介面,實際調用的時候會調用InvocationHandler實作類別中的invoke方法,而其中就是我們實現的代理業務,當然,也包括實際的業務。

這樣,對於有相同代理業務的類,我們只要實現InvocationHandler介面,在其中的invoke方法實現需要代理的業務,使用時只要使用Proxy.newProxyInstance靜態方法,傳入對應得參數即可得到需要的代理類,再將其強轉賦值給需要的介面,即可正常使用。

 

Java代理筆記

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.