1. 程式人生 > >JDK動態代理詳解(原始碼剖析)

JDK動態代理詳解(原始碼剖析)

一、什麼是代理?

代理是一種常用的設計模式,其目的就是為其他物件提供一個代理以控制對某個物件的訪問。代理類負責為委託類預處理訊息,過濾訊息並轉發訊息,以及進行訊息被委託類執行後的後續處理。

代理模式UML圖:


簡單結構示意圖:


為了保持行為的一致性,代理類和委託類通常會實現相同的介面,所以在訪問者看來兩者沒有絲毫的區別。通過代理類這中間一層,能有效控制對委託類物件的直接訪問,也可以很好地隱藏和保護委託類物件,同時也為實施不同控制策略預留了空間,從而在設計上獲得了更大的靈活性。Java 動態代理機制以巧妙的方式近乎完美地實踐了代理模式的設計理念。

二、Java 動態代理類 

Java動態代理類位於java.lang.reflect包下,一般主要涉及到以下兩個類:

(1)Interface InvocationHandler:該介面中僅定義了一個方法

  1. publicobject invoke(Object obj,Method method, Object[] args)  

在實際使用時,第一個引數obj一般是指代理類,method是被代理的方法,如上例中的request(),args為該方法的引數陣列。這個抽象方法在代理類中動態實現。

(2)Proxy:該類即為動態代理類,其中主要包含以下內容:

protected Proxy(InvocationHandler h):建構函式,用於給內部的h賦值。

static Class getProxyClass (ClassLoader

loader, Class[] interfaces):獲得一個代理類,其中loader是類裝載器,interfaces是真實類所擁有的全部介面的陣列。

static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)返回代理類的一個例項,返回後的代理類可以當作被代理類使用(可使用被代理類的在Subject介面中宣告過的方法)

所謂DynamicProxy是這樣一種class:它是在執行時生成的class在生成它時你必須提供一組interface給它,然後該class就宣稱它實現了這些 

interface。你當然可以把該class的例項當作這些interface中的任何一個來用。當然,這個DynamicProxy其實就是一個Proxy,它不會替你作實質性的工作,在生成它的例項時你必須提供一個handler,由它接管實際的工作

在使用動態代理類時,我們必須實現InvocationHandler介面

通過這種方式,被代理的物件(RealSubject)可以在執行時動態改變,需要控制的介面(Subject介面)可以在執行時改變,控制的方式(DynamicSubject)也可以動態改變,從而實現了非常靈活的動態代理關係。

動態代理步驟
1.建立一個實現介面InvocationHandler的類,它必須實現invoke方法
2.建立被代理的類以及介面
3.通過Proxy的靜態方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)建立一個代理
4.通過代理呼叫方法

三、JDK的動態代理怎麼使用?

1、需要動態代理的介面:
  1. package jiankunking;  
  2. /** 
  3.  * 需要動態代理的介面 
  4.  */
  5. publicinterface Subject  
  6. {  
  7.     /** 
  8.      * 你好 
  9.      * 
  10.      * @param name 
  11.      * @return 
  12.      */
  13.     public String SayHello(String name);  
  14.     /** 
  15.      * 再見 
  16.      * 
  17.      * @return 
  18.      */
  19.     public String SayGoodBye();  
  20. }  

2、需要代理的實際物件
  1. package jiankunking;  
  2. /** 
  3.  * 實際物件 
  4.  */
  5. publicclass RealSubject implements Subject  
  6. {  
  7.     /** 
  8.      * 你好 
  9.      * 
  10.      * @param name 
  11.      * @return 
  12.      */
  13.     public String SayHello(String name)  
  14.     {  
  15.         return"hello " + name;  
  16.     }  
  17.     /** 
  18.      * 再見 
  19.      * 
  20.      * @return 
  21.      */
  22.     public String SayGoodBye()  
  23.     {  
  24.         return" good bye ";  
  25.     }  
  26. }  

3、呼叫處理器實現類(有木有感覺這裡就是傳說中的AOP啊)
  1. package jiankunking;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. /** 
  5.  * 呼叫處理器實現類 
  6.  * 每次生成動態代理類物件時都需要指定一個實現了該介面的呼叫處理器物件 
  7.  */
  8. publicclass InvocationHandlerImpl implements InvocationHandler  
  9. {  
  10.     /** 
  11.      * 這個就是我們要代理的真實物件 
  12.      */
  13.     private Object subject;  
  14.     /** 
  15.      * 構造方法,給我們要代理的真實物件賦初值 
  16.      * 
  17.      * @param subject 
  18.      */
  19.     public InvocationHandlerImpl(Object subject)  
  20.     {  
  21.         this.subject = subject;  
  22.     }  
  23.     /** 
  24.      * 該方法負責集中處理動態代理類上的所有方法呼叫。 
  25.      * 呼叫處理器根據這三個引數進行預處理或分派到委託類例項上反射執行 
  26.      * 
  27.      * @param proxy  代理類例項 
  28.      * @param method 被呼叫的方法物件 
  29.      * @param args   呼叫引數 
  30.      * @return 
  31.      * @throws Throwable 
  32.      */
  33.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  
  34.     {  
  35.         //在代理真實物件前我們可以新增一些自己的操作
  36.         System.out.println("在呼叫之前,我要乾點啥呢?");  
  37.         System.out.println("Method:" + method);  
  38.         //當代理物件呼叫真實物件的方法時,其會自動的跳轉到代理物件關聯的handler物件的invoke方法來進行呼叫
  39.         Object returnValue = method.invoke(subject, args);  
  40.         //在代理真實物件後我們也可以新增一些自己的操作
  41.         System.out.println("在呼叫之後,我要乾點啥呢?");  
  42.         return returnValue;  
  43.     }  
  44. }  
4、測試
  1. package jiankunking;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Proxy;  
  4. /** 
  5.  * 動態代理演示 
  6.  */
  7. publicclass DynamicProxyDemonstration  
  8. {  
  9.     publicstaticvoid main(String[] args)  
  10.     {  
  11.         //代理的真實物件
  12.         Subject realSubject = new RealSubject();  
  13.         /** 
  14.          * InvocationHandlerImpl 實現了 InvocationHandler 介面,並能實現方法呼叫從代理類到委託類的分派轉發 
  15. 相關推薦

    JDK動態代理原始碼剖析

    一、什麼是代理? 代理是一種常用的設計模式,其目的就是為其他物件提供一個代理以控制對某個物件的訪問。代理類負責為委託類預處理訊息,過濾訊息並轉發訊息,以及進行訊息被委託類執行後的後續處理。代理模式UML圖:簡單結構示意圖:為了保持行為的一致性,代理類和委託類通常

    java jdk動態代理

            }       }       methods.add(generateStaticInitializer());   }   catch(IOException ioexception)   {       throw new InternalError("unexpected I/O

    JDK動態代理

    今年企業對Java開發的市場需求,你看懂了嗎? >>>   

    Type的子介面原始碼解析

    以下是原始碼中對Type的註釋:Type是Java中所有型別的常見的超介面,在程式語言中這些包括原始型別,引數化的型別,陣列型別,型別變數和原始型別。 Class在一定程度上挽救了擦除的型別資訊,我們就可以通過這幾個介面來獲取被擦除的型別引數資訊,這幾個介面無非就是對型別引數的一個

    openCV中的findHomography函式分析以及RANSAC演算法的原始碼分析

    本文將openCV中的RANSAC程式碼全部挑選出來,進行分析和講解,以便大家更好的理解RANSAC演算法。程式碼我都試過,可以直接執行。 在計算機視覺和影象處理等很多領域,都需要用到RANSAC演算法。openCV中也有封裝好的RANSAC演算法,以便於人們使用。關於RA

    java.util.Arrays類原始碼總結

    概述 Arrays類位於java.util包下,是一個對陣列操作的工具類。今天詳細的看了看Arrays類的4千多行原始碼,現將Arrays類中的方法做一個總結(JDK版本:1.6.0_34)。Arrays類中的方法可以分為八類: sort(對陣列排序) b

    cas客戶端流程原始碼解析--單點登入

    博主之前一直使用了cas客戶端進行使用者的單點登入操作,決定進行原始碼分析來看cas的整個流程,以便以後出現了問題還不知道是什麼原因導致的 cas主要的形式就是通過過濾器的形式來實現的,來,貼上示例配置: 1 <listener> 2 <listener-cl

    jdk動態代理 和 CGLIB動態代理

    1. 靜態代理模式 //目標介面 public interface IDoSomething { public void doSomething(); }//目標物件 public class DoSomething implements IDoSomething{

    mybatis與Spring三種開發方式二&三Mapper動態代理開發&Mapper動態代理掃描包形式開發

    mybatis與Spring三種開發方式詳解(二)Mapper動態代理開發 之前我們說到傳統的dao層開發,今天我們來談談第二種mybatis與Spring的開發方式,Mapper動態代理開發。 首先這裡上一波@test測試程式碼,大家先看一下mybat

    基於SpringBoot實現AOP+jdk/CGlib動態代理

    動態代理是一種設計模式。在Spring中,有倆種方式可以實現動態代理--JDK動態代理和CGLIB動態代理。 JDK動態代理 首先定義一個人的介面: public interface Person { void study(); } 然後接上一個Student class public class S

    2020了你還不會Java8新特性?收集器比較器用法原始碼剖析

    收集器用法詳解與多級分組和分割槽 為什麼在collectors類中定義一個靜態內部類? static class CollectorImpl<T, A, R> implements Collector<T, A, R> 設計上,本身就是一個輔助類,是一個工廠。作用是給開發者提供常見的

    動態代理

    font output 接口 col tle 訪問 AC 學習 stat 動態代理詳解 ? ?動態代理它可以直接給某一個目標對象生成一個代理對象,而不需要代理類存在。? ? 動態代理與代理模式原理是一樣的,只是它沒有具體的代理類,直接通過反射生成了一個代理對象。? ? 動

    iOS AppDelegate 代理啟動,開啟App,推送,通知

    //App將要啟動 - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(nullable NSDictionary *)launchOptions{ return YES;

    【linux】Valgrind工具集十二:DHAT:動態堆分析器

    一、概述 DHAT動態堆分析器。Massif(堆分析器)是在程式結束後輸出分析結果,而DHAT是實時輸出結果,所以叫做動態堆分析器。Massif只記錄堆記憶體的申請和釋放,DHAT還會分析堆空間的使用率、使用週期等資訊。 DHAT的功能:它首先記錄在堆上分配的塊,通過分析每次記憶體訪

    Java 動態代理

    部落格原文:http://laijianfeng.org/2018/12/Java-動態代理詳解/ 動態代理在Java中有著廣泛的應用,比如Spring AOP、Hibernate資料查詢、測試框架的後端mock、RPC遠端呼叫、Java註解物件獲取、日誌、使用者鑑權、

    Cocos2d—X遊戲開發之CCTableView十一原始碼

    本來很早就想寫關於CCTableView的文章,但是在基本功能實現之後呢,專案需求增加導致對這個控制元件的研究必須更加深入一點. 好的,現在開始介紹一下這個控制元件,在Cocos2d—X引擎中,這是一個仿製iOS裡面的NSTableView的一個控制元件。 S1,使用這個

    劍指offer(47):禮物的最大值動態規劃,python版

    本部落格主要內容為圖書《劍指offer》第二版47 題的解題思路及程式碼。方法可能還有不足之處,歡迎大家討論評論。 1. 題目描述   在一個 m*n 的棋盤中的每一個格都放一個禮物,每個禮物都有一定的價值(價值大於0).你可以從棋盤的左上角開始

    黑馬程式設計師-----高新技術-----動態代理

    ------<a href="http://www.itheima.com" target="blank">Java培訓、Android培訓、iOS培訓、.Net培訓</a>、期待與您交流! ------- 在學習Spring的時候,我們知道S

    黑馬程式設計師——動態代理

    /*  * 動態代理的作用  * 通過反射呼叫代理物件,讓其幫我們實現一些非常頻繁的操作,如:許可權校驗和日誌記錄  * 代理的實現原理:  * 在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler介面  * 通