第七講 動態代理

一、動態代理和靜態代理的角色是一樣的。

二、動態代理的代理類是動態生成的。

三、分爲兩類:基於接口的動態代理和基於類的動態代理。

  1. 基於接口的動態代理 --- JDK動態代理

  1. 基於類的動態代理 --- CGLib動態代理

     現在Javassist來生成動態代理。

四、JDK動態代理 --- InvocationHandler接口和Proxy類

     InvocationHandler接口:

   InvocationHandler 是代理實例的調用處理程序 實現的接口。

   每個代理實例都具有一個關聯的調用處理程序。對代理實例調用方法時,將對方法調用進行編碼並將其指派到它的調用處理程序的 invoke
   方法。
Object invoke(Object proxy, Method method, Object[] args)
          在代理實例上處理方法調用並返回結果。
在代理實例上處理方法調用並返回結果。在與方法關聯的代理實例上調用方法時,將在調用處理程序上調用此方法。
參數:
proxy - 在其上調用方法的代理實例
method - 對應於在代理實例上調用的接口方法的 Method 實例。Method 對象的聲明類將是在其中聲明方法的接口,該接口可以是代理類賴以繼承方法的代理接口的超接口。
args - 包含傳入代理實例上方法調用的參數值的對象數組,如果接口方法不使用參數,則爲 null。基本類型的參數被包裝在適當基本包裝器類(如 java.lang.Integerjava.lang.Boolean)的實例中。
返回:
從代理實例的方法調用返回的值。如果接口方法的聲明返回類型是基本類型,則此方法返回的值一定是相應基本包裝對象類的實例;否則,它一定是可分配到聲明返回類型的類型。如果此方法返回的值爲 null 並且接口方法的返回類型是基本類型,則代理實例上的方法調用將拋出 NullPointerException。否則,如果此方法返回的值與上述接口方法的聲明返回類型不兼容,則代理實例上的方法調用將拋出 ClassCastException
拋出:
Throwable - 從代理實例上的方法調用拋出的異常。該異常的類型必須可以分配到在接口方法的 throws 子句中聲明的任一異常類型或未經檢查的異常類型 java.lang.RuntimeExceptionjava.lang.Error。如果此方法拋出經過檢查的異常,該異常不可分配到在接口方法的 throws 子句中聲明的任一異常類型,代理實例的方法調用將拋出包含此方法曾拋出的異常的 UndeclaredThrowableException

     Proxy類:

  Proxy 提供用於創建動態代理類和實例的靜態方法,它還是由這些方法創建的所有動態代理類的超類。
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
          返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序。
返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序。此方法相當於:
     Proxy.getProxyClass(loader, interfaces).
         getConstructor(new Class[] { InvocationHandler.class }).
         newInstance(new Object[] { handler });
 

Proxy.newProxyInstance 拋出 IllegalArgumentException,原因與 Proxy.getProxyClass 相同。

參數:
loader - 定義代理類的類加載器
interfaces - 代理類要實現的接口列表
h - 指派方法調用的調用處理程序
返回:
一個帶有代理類的指定調用處理程序的代理實例,它由指定的類加載器定義,並實現指定的接口

     實現:

public class UserServiceImpl implements UserService {
     public void add() {
           System.out.println("增加用戶");
     }
     public void update() {
           System.out.println("修改用戶");
     }
     public void delete() {
           System.out.println("刪除用戶");
     }
     public void search() {
           System.out.println("查詢用戶");
     }
}

public class ProxyInvocationHandler implements InvocationHandler {
     
     //目標對象(真實對象,需要代理的對象)
     private Object target;
     
     public void setTarget(Object target) {
           this.target = target;
     }
     /**
      * 生成代理類
      */
     public Object getProxy() {
           return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                     target.getClass().getInterfaces(), this);
     }
     
     /**
      * proxy:代理類
      * method:代理類的調用處理程序的方法對象
      */
     public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
           log(method.getName());
           Object result = method.invoke(target, args);
           return result;
     }
     
     /**
      * 公共業務
      */
     public void log(String methodName) {
           System.out.println("執行" + methodName + "方法");
     }
     
}

public class Client {
     
     public static void main(String[] args) {
           UserService userService = new UserServiceImpl();
           ProxyInvocationHandler pih = new ProxyInvocationHandler();
           pih.setTarget(userService);
           UserService proxy = (UserService)pih.getProxy();
           proxy.add();
     }
     
}

   一個動態代理,一般代理某一類業務。一個動態代理可以代理多個類。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章