【Java入門提高篇】Day12 Java代理——Cglib動態代理

來源:互聯網
上載者:User

標籤:情況   ade   stc   java代理   []   cep   test   param   out   

  今天來介紹另一種更為強大的代理——Cglib動態代理。

  什麼是Cglib動態代理?

  我們先回顧一下上一篇的jdk動態代理,jdk動態代理是通過介面來在運行時動態建立委託類的代理對象,但是跟靜態代理一樣有一個缺點,就是必須和委託類實現相同的介面,當介面數量增加時,便需要增加代理類的數量才能滿足需求,而且如果委託類是別人寫的,而且沒有實現任何介面,那麼jdk動態代理就有些力不從心了。

  這時候Cglib動態代理就脫穎而出了,Cglib並不依賴介面,可以直接產生委託類的代理對象,而且可以代理委託類的任意非final修飾的public和protected方法,我們可以先來看一個栗子。

  先定義一個Programmer類:

public class Programmer {    private String name;        public void setName(String name) {
     System.out.println("Setting Name.");
this.name = name; }public void code(){ System.out.println(name + " is writing bugs."); }}

  然後定義一個代理類:

public class ProgrammerProxy implements MethodInterceptor {    /**     * 內部持有委託類對象的引用     */    private Object target;    /**     * 建立代理類對象     */    public Programmer createProxy(Programmer object){        target = object;        //建立Enhancer對象        Enhancer enhancer = new Enhancer();        //設定要代理的目標類,以擴充功能        enhancer.setSuperclass(this.target.getClass());        //設定單一回調對象,在回調中攔截對目標方法的調用        enhancer.setCallback(this);        //設定類載入器        enhancer.setClassLoader(object.getClass().getClassLoader());        //建立代理對象        return (Programmer)enhancer.create();    }    /**     * 回調方法:在代理執行個體上攔截並處理目標方法的調用,返回結果     * @param proxy  代理類     * @param method 被代理的方法     * @param params 該方法的參數數組     * @param methodProxy     */    @Override    public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {        //調用之前處理        doBefore();        //調用原方法        method.invoke(target,params);        //調用之後處理        doAfter();        return null;    }    private void doAfter() {        System.out.println("do after.");    }    private void doBefore() {        System.out.println("do before.");    }}

  然後測試一下:

public class ProxyTest {    @Test    public void testCglibProxy(){        //建立一個Programmer對象        Programmer programmerA = new Programmer();        programmerA.setName("Frank");        //建立代理對象        Programmer programmerProxyA = new ProgrammerProxy().createProxy(programmerA);        programmerProxyA.code();        //修改代理對象        programmerProxyA.setName("Wang");        programmerProxyA.code();        //修改委託類對象        programmerA.setName("Song");        programmerProxyA.code();    }}

  輸出如下:

Setting Name.do before.Frank is writing bugs.do after.do before.Setting Name.do after.do before.Wang is writing bugs.do after.Setting Name.do before.Song is writing bugs.do after.

  Cglib實現動態代理的步驟也不是很麻煩,先建立一個類實現MethodInterceptor介面,重寫intercept方法,在intercep中可以截獲委託類的所有非final修飾的public和protected方法,上例中,method.invoke(target,params);即為調用原對象的原方法,在代理類中儲存了委託類對象的引用,這一點跟JDK動態代理是一樣的。在調用原方法前先調用了doBefore方法,調用之後還調用了doAfter方法,從而實現了代理功能。至於createProxy方法,也只是一個固定步驟,先建立Enhance對象,然後將委託類的一些屬性往裡塞,然後調用create方法來動態組建代理程式對象。

  在測試類別中,為了更明顯的說明代理類與委託類的關係,分別用代理類對象programmerProxyA和委託類對象programmerA對name欄位進行修改,可以產生一樣的效果。

  下面來對比一下Cglib動態代理與JDK動態代理:

  1.兩者都是動態代理,都是運行時動態組建代理程式對象。

  2.JDK動態代理利用的是介面資訊來實現的代理,委託類必須實現某個或者某些介面,而Cglib則是利用繼承關係,利用asm在運行時動態產生委託類的子類,從而實現對委託類的代理。因此不依賴介面。

  3.Cglib由於是利用繼承關係來實現代理的,因此無法代理被final修飾的類以及被final修飾的方法。

  4.Cglib一般來說效率要比JDK動態代理效率更高,可以實現的代理也更為強大。

  當然,具體情況具體分析,雖然Cglib比Jdk動態代理更強大,但並不一定各個地方都強行使用,有時候JDK動態代理相對來說更加簡單粗暴。

  至此,本篇完結,代理相關內容講解完畢,歡迎大家繼續關注。

【Java入門提高篇】Day12 Java代理——Cglib動態代理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.