JDK動態(tài)代理和CGLib

動態(tài)代理介紹

應(yīng)用場景

假設(shè)現(xiàn)在已經(jīng)存在一個children接口墓拜,其中一個方法是eat()你家有個小孩myChild類循帐,你希望他講衛(wèi)生懂禮貌筝家,以后成為新世紀的四好少年旋讹,所以要讓他在吃飯前洗手瑰钮,為了能夠有時間打王者榮耀需要讓他在吃飯后就睡覺辙售。那這個時候的第一想法可能在children類中eat()方法的前后增加washHands和sleep的操作,或者增加方法washHand()和sleep()飞涂,然后在eat()方法中引用旦部。這兩種方法都可以解決這個問題,但是開閉原則告訴我們-對修改關(guān)閉╮(╯▽╰)╭较店。這樣就堵死了這兩種簡單的方式士八。在你一籌莫展的時候,動態(tài)代理就站在了你的面前梁呈,拯救你于水火之中婚度。

原理

我們在解決問題的時候往往想的就是簡單直接的解決當前面對的問題,但是現(xiàn)實的情況往往不能如愿官卡,既然不能夠直接修改myChild類蝗茁,那么就只能在你家小孩吃的之前增加一道洗手的程序,然后還是讓你的小孩吃飯寻咒,吃飯之后再增加一道睡覺的程序哮翘。這個時候就相當于在吃飯這個操作的前后增加了不同的操作,但是對于吃飯本身來說并沒有任何影響毛秘。

分類

動態(tài)代理分為兩種:JDK提供的動態(tài)代理和第三方的CGLib

JDK動態(tài)代理示例

JDK動態(tài)代理簡介

JDK動態(tài)代理顧名思義是由JDK提供的一種動態(tài)代理方式饭寺,簡介結(jié)束。

類圖

類圖1.png

具體代碼

撒話不說直接上代碼

接口Children

public interface Children {
    public void eat();
}

實現(xiàn)類MyChild

public class MyChild implements Children {
    @Override
    public void eat() {
        System.out.println("eat Something");
    }
}

處理類DynamicChildren

public class DynamicChildren implements InvocationHandler {
    private Object children;
    public DynamicChildren(Object object){
        this.children = object;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Wash Hands!");
//        調(diào)用實際實例的eat方法
        method.invoke(children, args);
        System.out.println("Sleep!");
        return null;
    }
}

客戶端Client

public class Client {
    public static void main(String[] args) {

        MyChild myChild = new MyChild();
        InvocationHandler handler = new DynamicChildren(myChild);
        Class<?> classType = handler.getClass();
        /*classType.getClassLoader():獲得DynamicChildren類加載器
        myChild.getClass().getInterfaces():獲得MyChild實現(xiàn)的所有接口類叫挟,當前的MyChild只實現(xiàn)了Children一類接口艰匙,所以這獲得的只有這個
        handler:DynamicChildren
        children即為生成的動態(tài)代理類*/
        Children children = (Children) Proxy.newProxyInstance(classType.getClassLoader(), myChild.getClass().getInterfaces(), handler);

//        這實際上是調(diào)用的DynamicChildren中的invoke方法
        children.eat();
    }
}

小結(jié)

以上就是我理解的JDK提供的動態(tài)代理相關(guān)的東西,完美是相對的抹恳,JDK動態(tài)代理也是一樣有優(yōu)缺點的员凝。

優(yōu)點

  • 不依賴第三方j(luò)ar包, 使用方便
  • 隨著JDK的升級,JDK動態(tài)代理的性能在穩(wěn)步提升

缺點

  • 只適用于實現(xiàn)了接口類
  • 執(zhí)行速度較慢

看了以上的內(nèi)容奋献,你的心中一定會冒出一個疑問健霹,如果沒有實現(xiàn)接口的類想要動態(tài)代理硕舆,是不是需要另外一種代理方式了呢?你猜的沒錯骤公!這個時候就到了另一種動態(tài)代理-CGLibの出番だ!

timg.jpg

CGLib簡介

CGLIB(Code Generation Library)是一個開源項目扬跋!
是一個強大的阶捆,高性能,高質(zhì)量的Code生成類庫钦听,它可以在運行期擴展Java類與實現(xiàn)Java接口洒试。Hibernate> 支持它來實現(xiàn)PO(Persistent Object 持久化對象)字節(jié)碼的動態(tài)生成。

以上摘自百度百科

CGLib的原理是通過字節(jié)碼技術(shù)為一個類創(chuàng)建子類朴上,并在子類中采用方法攔截的技術(shù)攔截當前類的所有父類方法的調(diào)用垒棋,順勢織入橫切邏輯。

使用的前置條件

需要在項目中依賴cglib相關(guān)的jar包和asm jar包痪宰。我使用的是cglib-2.2.jar叼架、cglib-nodep-2.2.jar和asm-3.2.jar。

類圖

類圖2.jpg

具體代碼

撒話不說直接上代碼

需要代理的類MyChild

public class MyChild {
    public void eat() {
        System.out.println("eat something");
    }
}

處理類CglibProxy

public class CglibProxy implements MethodInterceptor {
    private Enhancer enhancer = new Enhancer();
    public Object getProxy(Class clazz) {
//        設(shè)置需要創(chuàng)建動態(tài)代理類的類
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
//        通過字節(jié)碼動態(tài)創(chuàng)建實例
        return enhancer.create();
    }

    /**
     * 實現(xiàn) MethodInterceptor接口方法
     */
    @Override
    public Object intercept(Object obj, Method method, Object[] arg, MethodProxy proxy) throws Throwable {
        System.out.println("Wash Hands!");
//        通過代理類調(diào)用父類中的方法
        Object result = proxy.invokeSuper(obj, arg);
        System.out.println("Sleep!");
        return result;
    }
}

客戶端類DoCGLib

public class DoCGLib {
    public static void main(String[] args) {
        CglibProxy proxy = new CglibProxy();
//        通過生成子類的方式來生成代理類
        MyChild myChild = (MyChild) proxy.getProxy(MyChild.class);
        myChild.eat();
    }
}

小結(jié)

以上就是我理解的CGLib動態(tài)代理相關(guān)的東西衣撬,JDK動態(tài)代理有優(yōu)缺點乖订,那么CGLib動態(tài)代理也不能少。

優(yōu)點

  • 可以代理沒有實現(xiàn)接口的對象
  • 由于是動態(tài)生成字節(jié)碼實現(xiàn)代理具练,因此代理對象的執(zhí)行速度較快, 約為JDK動態(tài)代理的1.5 ~ 2倍

缺點

  • 不能代理final類
  • 動態(tài)生成字節(jié)碼雖然執(zhí)行較快乍构,但是生成速度很慢,根據(jù)網(wǎng)上一些人的測試結(jié)果扛点,CGLib創(chuàng)建代理對象的速度要比JDK慢10 ~ 15倍哥遮。

JDK動態(tài)代理和CGLib適用場景

  • 由于JDK動態(tài)代理在創(chuàng)建代理對象上比CGLib快,所以如果你的程序需要頻繁陵究、反復地創(chuàng)建代理對象眠饮,請將JDK動態(tài)代理定位為備胎一號。
  • 由于CGLib的執(zhí)行速度比JDK快铜邮,所以如果不需要頻繁創(chuàng)建代理對象的應(yīng)用君仆,如spring中默認的單例bean,只需要在容器啟動時生成一次代理對象這種情況牲距,請優(yōu)先考慮轉(zhuǎn)正CGLib返咱。

以上です!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牍鞠,一起剝皮案震驚了整個濱河市咖摹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌难述,老刑警劉巖萤晴,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吐句,死亡現(xiàn)場離奇詭異,居然都是意外死亡店读,警方通過查閱死者的電腦和手機嗦枢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來屯断,“玉大人文虏,你說我怎么就攤上這事≈逞荩” “怎么了氧秘?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長趴久。 經(jīng)常有香客問我丸相,道長,這世上最難降的妖魔是什么彼棍? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任灭忠,我火速辦了婚禮,結(jié)果婚禮上座硕,老公的妹妹穿的比我還像新娘更舞。我一直安慰自己,他們只是感情好坎吻,可當我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布缆蝉。 她就那樣靜靜地躺著,像睡著了一般瘦真。 火紅的嫁衣襯著肌膚如雪刊头。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天诸尽,我揣著相機與錄音原杂,去河邊找鬼。 笑死您机,一個胖子當著我的面吹牛穿肄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播际看,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼咸产,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了仲闽?” 一聲冷哼從身側(cè)響起脑溢,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赖欣,沒想到半個月后屑彻,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體验庙,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年社牲,在試婚紗的時候發(fā)現(xiàn)自己被綠了粪薛。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡搏恤,死狀恐怖违寿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情挑社,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布巡揍,位于F島的核電站痛阻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏腮敌。R本人自食惡果不足惜阱当,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糜工。 院中可真熱鬧弊添,春花似錦、人聲如沸捌木。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽刨裆。三九已至澈圈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帆啃,已是汗流浹背瞬女。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留努潘,地道東北人诽偷。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像疯坤,于是被迫代替她去往敵國和親报慕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容