Spring學習之動態(tài)代理

Spring學習之動態(tài)代理

前言

動態(tài)代理同蜻,是一種通過運行時操作字節(jié)碼闪湾,以達到增強類的功能的技術(shù)絮蒿,也是Spring AOP操作的基礎(chǔ)尊搬,關(guān)于AOP的內(nèi)容,將在后面的筆記中詳細講解土涝,本小節(jié)主要是理清楚動態(tài)代理佛寿,畢竟,Spring的AOP是基于動態(tài)代理技術(shù)但壮,對動態(tài)代理技術(shù)有所了解冀泻,對于學習Spring AOP也會有幫助

動態(tài)代理技術(shù)詳解

動態(tài)代理,現(xiàn)在主要是用于增強類的功能蜡饵,同時由于是具有動態(tài)性弹渔,所以避免了需要頻繁創(chuàng)建類的操作,同時溯祸,也使得原有的代碼在不需要改變的情況下肢专,對類的功能進行增強,主要的動態(tài)代理技術(shù)有:通過實現(xiàn)目標接口焦辅,重寫其方法博杖,以增強其能力,典型的以JDK動態(tài)代理為代表氨鹏;或者欧募,通過繼承類,重寫其方法以增強其能力仆抵,典型的以CGLib為代表跟继,這兩種技術(shù)分別從不同的方向來對類的能力進行擴充种冬,接下來來具體看下這兩種技術(shù)的特點以及差異。

基于JDK動態(tài)代理

基于JDK的動態(tài)代理技術(shù)舔糖,其主要特點就是目標類娱两,也就是需要被代理的類,必須有接口金吗,并且代理類必須實現(xiàn)跟它一樣的接口十兢,從而來起到代理其事務的功能,具體使用如下代碼所示摇庙,假設有一個UserService類旱物,主要用于負責用戶的登錄和退出,同時卫袒,有個日志類宵呛,負責記錄用戶的操作信息,直接將信息日志寫在對應的UserService實現(xiàn)類中夕凝,可以達到目的宝穗,但顯然這種方式不是很合理,特別是在UserService有很多個方法需要做日志記錄的時候码秉,就會使得日志記錄代碼遍布整個UserService逮矛,不僅使得代碼的冗余很大,而且當需要進行修改的時候转砖,也需要逐個修改须鼎,非常麻煩,這個時候堪藐,采用動態(tài)代理技術(shù)就是一種非常好的方法了莉兰。


/**
 * UserService接口
 */
interface UserService{

    void login();
    void logout();
}

/**
 * UseService實現(xiàn)類
 */
class UserServiceImpl implements UserService{

    @Override
    public void login() {
        System.out.println("someone login....");
    }

    @Override
    public void logout() {
        System.out.println("someone logout....");
    }
}


/**
 * 實現(xiàn)InvocationHandle接口挑围,用于織入所要增強的代碼
 */
class UserServiceHandle implements InvocationHandler{

    private UserService userService;

    public UserServiceHandle(UserService userService) {
        this.userService = userService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        LogService.info();
        Object object = method.invoke(userService, args);
        LogService.info();
        return object;
    }
}

/**
 * 代理類工廠礁竞,用于產(chǎn)生UseService類的代理類
 */
class ProxyFactory{

    public static UserService getProxyObject(UserService userService){

        // 使用JDK動態(tài)代理技術(shù)來創(chuàng)建對應的代理類
        return (UserService) Proxy.newProxyInstance(
                userService.getClass().getClassLoader(),
                userService.getClass().getInterfaces(),
                new UserServiceHandle(userService)
        );
    }
}

這樣,當我們需要使用UseService類的時候杉辙,只需要從ProxyFactory中獲取即可模捂,而且獲取的對象是UserService對象的代理類,也就是說蜘矢,獲得的對象是UserService對象的增強版

基于CGLib的動態(tài)代理技術(shù)

從上面的ProxyFactory工廠中可以看到狂男,在使用JDK進行創(chuàng)建動態(tài)代理對象的時候,需要為其提供接口品腹,或者說岖食,如果所要增強的目標類沒有實現(xiàn)任何接口,則JDK動態(tài)代理技術(shù)是無法為其創(chuàng)建對應的代理對象的舞吭,這是JDK動態(tài)代理技術(shù)的一種缺點泡垃,而CGLib動態(tài)代理技術(shù)則恰好彌補了這個缺點析珊,CGLib動態(tài)代理技術(shù)使用的是繼承該類的方式,從而避免了需要接口的缺陷蔑穴,具體使用如下所示忠寻,注意,需要導入對應的依賴文件


/**
 * 基于CGLib的動態(tài)代理技術(shù)
 * 注意這里需要實現(xiàn)MethodInterceptor接口
 */
class ProxyFactory implements MethodInterceptor{

    // 提供對應的增強操作類
    private  Enhancer enhancer = new Enhancer();

    public UserService getProxyObject(Class clazz){
        // 設置所要增強的類的父類
        enhancer.setSuperclass(clazz);
        // 設置回調(diào)對象
        enhancer.setCallback(this);
        // 創(chuàng)建對應的對象
        return (UserService) enhancer.create();
    }

    // 實現(xiàn)攔截方法存和,用于攔截對應的方法奕剃,并且對對應的方法進行增強
    // 參數(shù)含義:傳入的對象, Method對象捐腿,方法的參數(shù)纵朋,進行代理后的Method對象
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        LogService.info();
        // 這里需要注意,由于methodProxy對象是增強后的Method對象茄袖,所以這里需要調(diào)用的
        // 是methodProxy父類的方法倡蝙,也就是所以增強的類的方法,以實現(xiàn)原來的功能
        Object object = methodProxy.invokeSuper(o, objects);
        LogService.info();
        return object;
    }
}

可以看到绞佩,使用CGLib動態(tài)代理技術(shù)可以在不需要實現(xiàn)接口的情況下東塔為對象創(chuàng)建代理對象寺鸥,在很大程度上彌補了JDK動態(tài)代理技術(shù)的缺點,不過由于CGLib動態(tài)代理技術(shù)是采用繼承目標類的方式品山,所以也存在一些問題胆建,比如說,對于final以及private修飾的方法是無法為其增強的肘交,這里還需要注意一下笆载。

總結(jié)

動態(tài)代理技術(shù)是實現(xiàn)AOP技術(shù)的基礎(chǔ),也是一種很方便地實現(xiàn)方式涯呻,常用的動態(tài)代理技術(shù)有基于JDK動態(tài)代理技術(shù)以及基于CGLib的動態(tài)代理技術(shù)凉驻,兩種技術(shù)各有千秋,也都各有缺點基于JDK的動態(tài)代理技術(shù)需要為其提供接口复罐,基于CGLib的動態(tài)代理技術(shù)不能為final以及private修飾的方法進行增強涝登,在使用的時候需要根據(jù)具體進行進行合理選擇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末效诅,一起剝皮案震驚了整個濱河市胀滚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乱投,老刑警劉巖咽笼,帶你破解...
    沈念sama閱讀 222,627評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異戚炫,居然都是意外死亡剑刑,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評論 3 399
  • 文/潘曉璐 我一進店門双肤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來施掏,“玉大人层宫,你說我怎么就攤上這事∑浼啵” “怎么了萌腿?”我有些...
    開封第一講書人閱讀 169,346評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長抖苦。 經(jīng)常有香客問我毁菱,道長,這世上最難降的妖魔是什么锌历? 我笑而不...
    開封第一講書人閱讀 60,097評論 1 300
  • 正文 為了忘掉前任贮庞,我火速辦了婚禮,結(jié)果婚禮上究西,老公的妹妹穿的比我還像新娘窗慎。我一直安慰自己,他們只是感情好卤材,可當我...
    茶點故事閱讀 69,100評論 6 398
  • 文/花漫 我一把揭開白布遮斥。 她就那樣靜靜地躺著,像睡著了一般扇丛。 火紅的嫁衣襯著肌膚如雪术吗。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,696評論 1 312
  • 那天帆精,我揣著相機與錄音较屿,去河邊找鬼。 笑死卓练,一個胖子當著我的面吹牛隘蝎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播襟企,決...
    沈念sama閱讀 41,165評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼嘱么,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了整吆?” 一聲冷哼從身側(cè)響起拱撵,我...
    開封第一講書人閱讀 40,108評論 0 277
  • 序言:老撾萬榮一對情侶失蹤辉川,失蹤者是張志新(化名)和其女友劉穎表蝙,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乓旗,經(jīng)...
    沈念sama閱讀 46,646評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡府蛇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,709評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了屿愚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汇跨。...
    茶點故事閱讀 40,861評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡务荆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出穷遂,到底是詐尸還是另有隱情函匕,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布蚪黑,位于F島的核電站盅惜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏忌穿。R本人自食惡果不足惜抒寂,卻給世界環(huán)境...
    茶點故事閱讀 42,196評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掠剑。 院中可真熱鬧屈芜,春花似錦、人聲如沸朴译。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽眠寿。三九已至毅糟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間澜公,已是汗流浹背姆另。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留坟乾,地道東北人迹辐。 一個月前我還...
    沈念sama閱讀 49,287評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像甚侣,于是被迫代替她去往敵國和親明吩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,860評論 2 361

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

  • 今天內(nèi)容介紹 Spring框架的IOC基于注解的方式 注解類型 注解生命周期 Spring框架整合JUnit單元測...
  • 0.前言 本文主要想闡述的問題如下:什么動態(tài)代理(AOP)以及如何用JDK的Proxy和InvocationHan...
    SYFHEHE閱讀 2,284評論 1 7
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理殷费,服務發(fā)現(xiàn)印荔,斷路器,智...
    卡卡羅2017閱讀 134,715評論 18 139
  • 在理解Spring AOP以及理清它與Aspect和cglib之間關(guān)系之前详羡,有很多基礎(chǔ)工作要做仍律,比如,先對代理模式...
    maxwellyue閱讀 1,249評論 0 5
  • 從三月份找實習到現(xiàn)在实柠,面了一些公司水泉,掛了不少,但最終還是拿到小米、百度草则、阿里钢拧、京東、新浪炕横、CVTE源内、樂視家的研發(fā)崗...
    時芥藍閱讀 42,278評論 11 349