今天,我就來講一下動態代理的設計模式,
動態代理的意義在于生成一個代理物件,來代理真實物件,從而控制真實物件的訪問,操作動態代理需要兩個步驟:一、代理物件和真實物件建立代理關系,二、實作代理物件的代理邏輯方法,
在Java中,有很多的動態代理技術,如:JDK、CGLIB、Javassist、ASM,其中最常用的動態代理技術有兩種:一種是JDK動態代理,這是JDK自帶的功能;另一種就是CGLIB,這是第三方提供的一種技術,
這次主要講的是JDK動態代理和CGLIB動態代理,在JDK動態代理中,我們必須使用介面,而CGLIB就不需要,
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動態代理,我們先要建立代理物件和真實服務物件的關系,然后實作代理邏輯,
在 JDK 動態代理中,要實作代理邏輯類必須去實作 java.lang.reflect.InvocationHandler 介面,它里面定義了一個 invoke 方法,并且提供介面陣列用于下掛代理物件,代碼如下:
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 動態代理,它是一種常用的動態代理,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/37809.html
標籤:設計模式
