天天看點

動态代理1、什麼是動态代理?2、主要技術3、動态代理的用途4、動态代理的兩種表現形式5、動态代理各個角色分析6、動态代理的優點

  動态代理就是在運作時生成一個類,這個類會實作你指定的一組接口,而這個類沒有.java檔案,是在運作時生成的,你也不用去關心它是什麼類型的,你隻需要知道它實作了哪些接口即可。

  平常實作一個接口需要寫一個具體的實作類,而動态代理技術能夠在運作期間動态的生成實作指定接口的實作類對象,底層使用的反射原理。在架構中經常使用,例如:struts1、struts2、spring和hibernate等等。學習動态代理可以更好的了解架構内部的原理。

  建立動态代理的方法:

  上面代碼中,proxy類的靜态方法newproxyinstance()方法生成了一個對象,這個對象實作了數組中指定的接口。proxy類的靜态方法newproxyinstance()方法傳回的是實作了指定接口的實作類對象。

  newproxyinstance()方法的參數:

    classloader loader:它是類加載器類型,myinterface.class.getclassloader()就可以擷取到classloader對象,隻要有一個class對象就可以擷取到classloader對象;

    class[] interfaces:指定newproxyinstance()方法傳回的對象要實作哪些接口,可以指定多個接口,例如上面例子我們隻指定了一個接口;

    invocationhandler h:它是最重要的一個參數,是一個接口!叫做調用處理器,無論你調用代理對象的什麼方法,都是在調用invocationhandler的invoke()方法!

  invocationhandler的invoke()方法:

  invocationhandler的invoke()方法的參數有三個:

    object proxy:代理對象,也就是proxy.newproxyinstance()方法傳回的對象,通常不用;

    method method:表示目前被調用方法的反射對象;

    object[] args:表示目前被調用方法的參數,沒有參數的args是一個零長數組。

  invoke()方法的傳回值為object類型,它表示目前被調用的方法的傳回值,沒有傳回值的invoke()傳回的就必須是null。

  動态代理作為代理模式的一種擴充形式,廣泛應用于架構(尤其是基于aop的架構)的設計與開發,動态代理的用途與裝飾模式很相似,就是為了對某個對象進行增強。所有使用裝飾者模式的案例都可以使用動态代理來替換。

  在java類加載器中也應用了代理模式,例如我們自己寫的person類,一定是存放到classpath中,那麼一定是由系統類加載器來加載。當系統類加載器來加載類時,它首先把加載的任務交給擴充類加載去,如果擴充類加載器加載成功了,那麼系統類加載器就不會再去加載。這就是代理模式了!

  代理模式保證了jdk中的類一定是由引導類加載器加載的!這就不會出現多個版本的類,這也是代理模式的好處。

  給出invocationhandler接口具體實作類:

  接口:

  

  接口實作類(待增強對象所屬類):

  invocationhandler實作類:

  測試類:

  這樣,根據執行方法的不同就會調用不同的效果了。

  使用内部類形式:

  因為這個沒有給出invocationhandler接口實作類,是以需要使用匿名内部類的形式。

  抽象角色:聲明真實對象和代理對象的共同接口,這樣一來在任何可以使用目标對象的地方都可以使用代理對象。

  代理角色:代理對象内部含有目标對象的引用,進而可以在任何時候操作目标對象;代理對象提供一個與目标對象相同的接口,以便可以在任何時候替代目标對象。代理對象通常在用戶端調用傳遞給目标對象之前或之後,執行某個操作,而不是單純地将調用傳遞給目标對象,同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當于對真實對象進行封裝。

  真實角色:定義了代理對象所代表的目标對象,代理角色所代表的真實對象,是我們最終要引用的對象,定義了代理對象所代表的目标對象。

  減少程式設計的工作量:假如需要實作多種代理處理邏輯,隻要寫多個代理處理器就可以了,無需每種方式都寫一個代理類。

  系統擴充性和維護性增強,程式修改起來也友善多了(一般隻要改代理處理器類就行了)。

  做方法的增強,可以在不修改源碼的情況下,增強一些方法,實作無侵入式的代碼擴充。

動态代理1、什麼是動态代理?2、主要技術3、動态代理的用途4、動态代理的兩種表現形式5、動态代理各個角色分析6、動态代理的優點