Java動(dòng)態(tài)代理總結(jié)

概念介紹

靜態(tài)代理
由程序員主動(dòng)創(chuàng)建或由特定工具自動(dòng)生成源代碼,再對(duì)其編譯炮叶。在程序運(yùn)行前,代理類的.class文件就已經(jīng)存在了渡处。

動(dòng)態(tài)代理
代理類在程序運(yùn)行前并不存在镜悉,在程序運(yùn)行時(shí)動(dòng)態(tài)生成(無需手工編寫代理類源碼)
實(shí)現(xiàn)原理:Java反射機(jī)制

實(shí)現(xiàn)原理

Java編譯器編譯好Java文件之后,產(chǎn)生.class 文件在磁盤中医瘫。這種class文件是二進(jìn)制文件侣肄,內(nèi)容是只有JVM虛擬機(jī)能夠識(shí)別的機(jī)器碼。JVM虛擬機(jī)讀取字節(jié)碼文件醇份,取出二進(jìn)制數(shù)據(jù)稼锅,加載到內(nèi)存中吼具,解析.class 文件內(nèi)的信息,生成對(duì)應(yīng)的 Class對(duì)象:

.class文件加載過程

由于JVM通過字節(jié)碼的二進(jìn)制信息加載類的矩距,那么拗盒,如果我們?cè)谶\(yùn)行期系統(tǒng)中,遵循Java編譯系統(tǒng)組織.class文件的格式和結(jié)構(gòu)锥债,生成相應(yīng)的二進(jìn)制數(shù)據(jù)陡蝇,然后再把這個(gè)二進(jìn)制數(shù)據(jù)加載轉(zhuǎn)換成對(duì)應(yīng)的類,這樣哮肚,就完成了在代碼中登夫,動(dòng)態(tài)創(chuàng)建一個(gè)類的能力了。

動(dòng)態(tài)創(chuàng)建類

具體實(shí)現(xiàn)

  • 接口TargetInterface
public interface TargetInterface {
    public int targetMethodA(int number);  
    public int targetMethodB(int number);
}
  • 具體實(shí)現(xiàn)類ConcreteClass
public class ConcreteClass implements TargetInterface {

    @Override
    public int targetMethodA(int number) {
        System.out.println("開始調(diào)用目標(biāo)類的方法targetMethodA...");  
        System.out.println("操作-打印數(shù)字:"+number);  
        System.out.println("結(jié)束調(diào)用目標(biāo)類的方法targetMethodA...");  
        return number;  
    }

    @Override
    public int targetMethodB(int number) {
        System.out.println("開始調(diào)用目標(biāo)類的方法targetMethodB...");  
        System.out.println("操作-打印數(shù)字:"+number);  
        System.out.println("結(jié)束調(diào)用目標(biāo)類的方法targetMethodB...");  
        return number;  
    }

}
  • 動(dòng)態(tài)代理類ProxyHandler
    調(diào)用代理類目標(biāo)接口方法時(shí)允趟,對(duì)自動(dòng)將其轉(zhuǎn)發(fā)到代理處理器中的invoke()方法中恼策,invoke()方法內(nèi)部可以實(shí)現(xiàn)預(yù)處理,對(duì)委托類方法調(diào)用潮剪,后續(xù)處理等邏輯戏蔑。
public class ProxyHandler implements InvocationHandler {

    private Object concreteClass;  
    
    public ProxyHandler(Object concreteClass){  
        this.concreteClass=concreteClass;  
    }  
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        System.out.println("proxy:"+proxy.getClass().getName());  
        System.out.println("method:"+method.getName());  
        System.out.println("args:"+args[0].getClass().getName());  
          
        System.out.println("Before invoke method...");  
        Object object=method.invoke(concreteClass, args);//普通的Java反射代碼,通過反射執(zhí)行某個(gè)類的某方法  
        //System.out.println(((ConcreteClass)concreteClass).targetMethod(10)+(Integer)args[0]);  
        System.out.println("After invoke method...");  
        return object;  
    }  

}
  • 測(cè)試類DynamicProxyExample
public class DynamicProxyExample {
    public static void main(String[] args){  
        ConcreteClass c=new ConcreteClass();//元對(duì)象(被代理對(duì)象)  
        InvocationHandler ih=new ProxyHandler(c);//代理實(shí)例的調(diào)用處理程序。  
        //創(chuàng)建一個(gè)實(shí)現(xiàn)業(yè)務(wù)接口的代理類,用于訪問業(yè)務(wù)類(見代理模式)鲁纠。  
        //返回一個(gè)指定接口的代理類實(shí)例总棵,該接口可以將方法調(diào)用指派到指定的調(diào)用處理程序,如ProxyHandler改含。  
        TargetInterface targetInterface=  
            (TargetInterface)Proxy.newProxyInstance(c.getClass().getClassLoader(),c.getClass().getInterfaces(),ih);  
        //調(diào)用代理類方法,Java執(zhí)行InvocationHandler接口的方法.  
        int i=targetInterface.targetMethodA(5);  
        System.out.println(i);  
        System.out.println();  
        int j=targetInterface.targetMethodB(15);  
        System.out.println(j);  
   }  
}

優(yōu)點(diǎn)

  1. 減少編程的工作量:假如需要實(shí)現(xiàn)多種代理處理邏輯情龄,只要寫多個(gè)代理處理器就可以了,無需每種方式都寫一個(gè)代理類捍壤。
  2. 系統(tǒng)擴(kuò)展性和維護(hù)性增強(qiáng)骤视,程序修改起來也方便多了(一般只要改代理處理器類就行了)。

不足

目前根據(jù)GOF的代理模式鹃觉,代理類和委托類需要都實(shí)現(xiàn)同一個(gè)接口(在代理類實(shí)例化時(shí)需傳入目標(biāo)接口)专酗。也就是說只有實(shí)現(xiàn)了某個(gè)接口的類可以使用Java動(dòng)態(tài)代理機(jī)制。但是盗扇,事實(shí)上使用中并不是遇到的所有類都會(huì)給你實(shí)現(xiàn)一個(gè)接口祷肯。因此,對(duì)于沒有實(shí)現(xiàn)接口的類疗隶,目前無法使用該機(jī)制佑笋。

參考資料

[1]Java動(dòng)態(tài)代理機(jī)制詳解(JDK 和CGLIB,Javassist斑鼻,ASM)
[2]Java動(dòng)態(tài)代理詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蒋纬,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蜀备,老刑警劉巖关摇,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異碾阁,居然都是意外死亡拒垃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門瓷蛙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悼瓮,“玉大人,你說我怎么就攤上這事艰猬『岜ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵冠桃,是天一觀的道長(zhǎng)命贴。 經(jīng)常有香客問我,道長(zhǎng)食听,這世上最難降的妖魔是什么胸蛛? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮樱报,結(jié)果婚禮上葬项,老公的妹妹穿的比我還像新娘。我一直安慰自己迹蛤,他們只是感情好民珍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盗飒,像睡著了一般嚷量。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逆趣,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天蝶溶,我揣著相機(jī)與錄音,去河邊找鬼宣渗。 笑死抖所,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的落包。 我是一名探鬼主播部蛇,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼咐蝇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤有序,失蹤者是張志新(化名)和其女友劉穎抹腿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旭寿,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡警绩,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盅称。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肩祥。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖缩膝,靈堂內(nèi)的尸體忽然破棺而出混狠,到底是詐尸還是另有隱情,我是刑警寧澤疾层,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布将饺,位于F島的核電站,受9級(jí)特大地震影響痛黎,放射性物質(zhì)發(fā)生泄漏予弧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一湖饱、第九天 我趴在偏房一處隱蔽的房頂上張望掖蛤。 院中可真熱鬧,春花似錦井厌、人聲如沸坠七。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彪置。三九已至,卻和暖如春蝇恶,著一層夾襖步出監(jiān)牢的瞬間拳魁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工撮弧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留潘懊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓贿衍,卻偏偏與公主長(zhǎng)得像授舟,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贸辈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理释树,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法奢啥,類相關(guān)的語法秸仙,內(nèi)部類的語法,繼承相關(guān)的語法桩盲,異常的語法寂纪,線程的語...
    子非魚_t_閱讀 31,630評(píng)論 18 399
  • 你是不是覺得寫一段故事是個(gè)特別麻煩的事兒捞蛋,你壓根都不知道從哪兒開始。 我從《開發(fā)故事創(chuàng)意》這本書獲得的啟發(fā)是柬姚,沒準(zhǔn)...
    聞熙閱讀 289評(píng)論 0 0
  • 塵埃落定拟杉,該有結(jié)果的均都有了結(jié)果。今天的我伤靠,心里滿滿的感動(dòng)捣域,也讓我明白心懷感恩的重要性⊙绾希恍然大悟的那一瞬間焕梅,心里暖...
    靜寶sz閱讀 112評(píng)論 0 0
  • 導(dǎo)語:生活處處是銷售贞言,銷售做的好的人往往為人處世也不會(huì)差!年輕的美女老板娘阀蒂,開了自己的店该窗,卻苦于找不到精準(zhǔn)的客戶群...
    lh事在人為閱讀 576評(píng)論 1 0