深入淺出JDK動態代理(一),深入淺出jdk動態代理

來源:互聯網
上載者:User

深入淺出JDK動態代理(一),深入淺出jdk動態代理

1.何為代理
  代理,即代替主角完成一些額外的事情。例如,明星都有經紀人,明星參演電影之前,經紀人作為明星的代理人和出資方洽談片酬、排期等,而真正參與拍戲的還是明星本人,明星拍完戲後,由經紀人代理明星去清算片酬等。Java中的代理機制就是在目標方法執行前後執行一些額外的操作,如安全檢查、記錄日誌等,Java中的代理分為靜態代理和動態代理。

2.靜態代理
  首先看一下靜態代理,直接上代碼,代碼類比了登入操作。

public interface LoginService {    void login();}public class LoginServiceImpl implements LoginService {    @Override    public void login() {        System.out.println("login");    }}public class LoginServiceProxy implements LoginService {    private LoginService loginService;    public LoginServiceProxy(LoginService loginService) {        this.loginService = loginService;    }    @Override    public void login() {        beforeLogin();        loginService.login();        afterLogin();    }    private void beforeLogin() {        System.out.println("before login");    }    private void afterLogin() {        System.out.println("after login");    }}public class Client {    @Test    public void test() {        LoginService loginService = new LoginServiceImpl();        LoginService loginServiceProxy = new LoginServiceProxy(loginService);        loginServiceProxy.login();    }}

輸出結果如下:

before loginloginafter login

上面代碼實現的靜態代理很容易理解,使用彙總方式,在登入操作前後執行額外的操作。靜態代理方式可以看得到具體代理類的代碼,且代碼由程式員編寫,在編譯之後會產生相應的class檔案。使用靜態代理方式的缺點,如果需要對LoginService介面中有N個方法都代理,則需要在代理類中建立N個代理方法,並且需要編寫重複的代理作業碼。

3.概念解釋
  目標介面,即對目標操作的抽象,如LoginService。
  目標類,即目標介面的實作類別,如LoginServiceImpl。
  目標對象,即目標類的執行個體。
  代理類,即目標類的代理,如LoginServiceProxy。
  代理對象,即代理類的執行個體。

4.動態代理
  動態代理,即在運行時根據目標介面動態產生的代理類。動態代理方式產生的代理類在編譯後不會產生實際的class檔案,而是在運行時動態產生類位元組碼,並載入到JVM中使用。下面使用JDK的動態代理機制類比登入操作,具體代碼如下。

public interface LoginService {    void login();}public class LoginServiceImpl implements LoginService {    @Override    public void login() {        System.out.println("login");    }}public class ProxyInvocationHandler implements InvocationHandler {    private LoginService loginService;    public ProxyInvocationHandler(LoginService loginService) {        this.loginService = loginService;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        beforeLogin();        Object invokeResult = method.invoke(loginService, args);        afterLogin();        return invokeResult;    }    private void beforeLogin() {        System.out.println("before login");    }    private void afterLogin() {        System.out.println("after login");    }}public class Client {    @Test    public void test() {        LoginService loginService = new LoginServiceImpl();        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler(loginService);        LoginService loginServiceProxy = (LoginService) Proxy.newProxyInstance(loginService.getClass().getClassLoader(), loginService.getClass().getInterfaces(), proxyInvocationHandler);        loginServiceProxy.login();        createProxyClassFile();    }    public static void createProxyClassFile() {        String name = "LoginServiceProxy";        byte[] data = ProxyGenerator.generateProxyClass(name, new Class[]{LoginService.class});        try {            FileOutputStream out = new FileOutputStream("/Users/" + name + ".class");            out.write(data);            out.close();        } catch (Exception e) {            e.printStackTrace();        }    }}

  輸出結果如下。

before loginloginafter login

  JDK動態代理方式實現代理的步驟如下:
  1.編寫目標介面;
  2.編寫目標類實現目標介面,實現目標方法的具體邏輯;
  3.編寫一個代理處理器類實現InvocationHandler介面,重寫invoke方法,用於指定運行時將產生的代理類需要完成的具體操作,包括beforeLogin和afterLogin。代理對象調用任何代理方法時都會調用這個invoke方法;
  4.建立代理對象,使用代理對象調用代理方法。

  上面的步驟中主要涉及以下兩個類:java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy。InvocationHandler是一個介面,代理類的調用處理器,每個代理對象都具有一個關聯的調用處理器,用於指定動態產生的代理類需要完成的具體操作。該介面中有一個invoke方法,代理對象調用任何目標介面的方法時都會調用這個invoke方法,在這個方法中進行目標類的目標方法的調用。Proxy提供靜態方法用於建立動態代理類和代理類執行個體,同時,使用它提供的方法建立的代理類都是它的子類。這個類中主要關注newProxyInstance方法,該方法用於建立代理類對象,方法聲明如下:

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

loader參數用於指示使用哪個類載入器載入這個代理類;interfaces表示代理類實現的介面列表;h表示使用哪個調用處理器。

  後續文章《深入淺出JDK動態代理(二)》會深入源碼分析JDK動態代理產生的代理類是什麼樣,為什麼調用代理類的任何方法時都一定會調用invoke方法,值得期待!

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.