動態代理模式——JDK動態代理

  今天,我就來說一下動態代理的設計模式。java

  動態代理的意義在於生成一個代理對象,來代理真實對象,從而控制真實對象的訪問。操做動態代理須要兩個步驟:1、代理對象和真實對象創建代理關係。2、實現代理對象的代理邏輯方法。設計模式

  在Java中,有不少的動態代理技術。如:JDK、CGLIB、Javassist、ASM,其中最經常使用的動態代理技術有兩種:一種是JDK動態代理,這是JDK自帶的功能;另外一種就是CGLIB,這是第三方提供的一種技術。數組

  此次主要講的是JDK動態代理和CGLIB動態代理。在JDK動態代理中,咱們必須使用接口,而CGLIB就不須要。ide

 

JDK 動態代理

  JDK 動態代理是 java.lang.reflect.* 包提供的方式,它必須藉助一個接口才能產生代理對象,因此咱們先定義一個接口。代碼以下:學習

1 public interface HelloWorld {
2 
3     public void sayHelloWorld();
4 }

  而後提供實現類來實現此接口。代碼以下:測試

public class HelloWorldImpl implements HelloWorld {

    @Override
    public void sayHelloWorld() {
        System.out.println("Hello World! 動態代理學習篇");
    }

}

  這是最簡單的 Java 接口與實現類的關係。這時咱們開始今天學習的內容,JDK動態代理。咱們先要創建代理對象和真實服務對象的關係,而後實現代理邏輯。this

  在 JDK 動態代理中,要實現代理邏輯類必須去實現 java.lang.reflect.InvocationHandler 接口,它裏面定義了一個 invoke 方法,而且提供接口數組用於下掛代理對象。代碼以下:spa

public class JdkProxy implements InvocationHandler {
    
    //真實對象
    private Object target = null;
    
    /**
     * 創建代理對象和真實對象的代理關係,並返回代理對象
     * @param obj 真實對象
     * @return           代理對象
     */
    public Object bind(Object target){
        this.target = target;
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    /**
     * 代理方法邏輯
     * @param proxy    代理對象
     * @param method 當前調度方法
     * @param args 當前方法的參數
     * @return 代理結果返回
     * @throws 異常
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("進入代理邏輯方法");
        System.out.println("在調度真實對象以前的服務");
        //至關於調用 sayHelloWorld 的方法
        Object obj = method.invoke(target, args);
        System.out.println("在調度真實對象以後的服務");
        return obj;
    }

}

  第1步,創建代理對象和真實對象的關係。這裏使用 bind 方法去完成,方法裏面首先用類的屬性 target 保存了真實對象,而後經過以下代碼創建並生成代理對象。設計

Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);

  其中 newProxyInstance 方法包含三個參數。代理

  第一個參數爲:類加載器。

  第二個參數爲:把生成的動態代理對象下掛在哪些接口下。

  第三個參數爲:定義實現方法邏輯的代理類,this 表示當前對象,它必須實現 InvocationHandler 接口方法的 invoke 方法,它就是代理邏輯方法的現實方法。

  第2步,實現代理邏輯方法。 invoke 方法能夠實現代理邏輯, invoke 方法的三個參數的意義以下:

  proxy:代理對象,就是 bind 方法生成的對象。

  method:當前調度的方法。

  args: 調度方法的參數。

 

測試一下JDK動態代理方法。代碼以下:

public class TestProxy {
    
    public static void main(String[] args) {
        JdkProxy jdkTest = new JdkProxy();
        HelloWorld proxy = (HelloWorld)jdkTest.bind(new HelloWorldImpl());
        proxy.sayHelloWorld();
        
    }

}

測試結果以下:

 

  這就是 JDK 動態代理,它是一種經常使用的動態代理。

相關文章
相關標籤/搜索