今天,我就來說一下動態代理的設計模式。java
動態代理的意義在於生成一個代理對象,來代理真實對象,從而控制真實對象的訪問。操做動態代理須要兩個步驟:1、代理對象和真實對象創建代理關係。2、實現代理對象的代理邏輯方法。設計模式
在Java中,有不少的動態代理技術。如:JDK、CGLIB、Javassist、ASM,其中最經常使用的動態代理技術有兩種:一種是JDK動態代理,這是JDK自帶的功能;另外一種就是CGLIB,這是第三方提供的一種技術。數組
此次主要講的是JDK動態代理和CGLIB動態代理。在JDK動態代理中,咱們必須使用接口,而CGLIB就不須要。ide
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 動態代理,它是一種經常使用的動態代理。