摘要:要明白,動(dòng)態(tài)代理類的存在意義是為了攔截方法并修改邏輯而動(dòng)態(tài)代理的局限性之一就是只能攔截接口所聲明的方法。因?yàn)閯?dòng)態(tài)代理類是繼承自業(yè)務(wù)類,所以該類和方法不能聲明成無(wú)法繼承或重寫。者最終都是生成了一個(gè)新的動(dòng)態(tài)代理類對(duì)象。
動(dòng)態(tài)代理 1、先談靜態(tài)代理
對(duì)于靜態(tài)代理,我們已經(jīng)很熟悉了。我們擁有一個(gè)抽象類,真實(shí)類繼承自抽象類并重寫其業(yè)務(wù)方法,代理類持有真實(shí)類的對(duì)象實(shí)例,在重寫業(yè)務(wù)方法中通過(guò)調(diào)用真實(shí)類的方法,并且添加自己的邏輯。這樣代理類就實(shí)現(xiàn)了對(duì)真實(shí)類的行為代理。
靜態(tài)代理的缺點(diǎn)在于,我們需要實(shí)現(xiàn)多個(gè)代理類,這無(wú)疑是很崩潰的。
2、JDK動(dòng)態(tài)代理優(yōu)點(diǎn)先行:我們說(shuō)靜態(tài)代理的缺點(diǎn)在于需要為每一個(gè)真實(shí)類都生成一個(gè)對(duì)應(yīng)的代理類,這樣就很繁瑣。動(dòng)態(tài)代理呢,我們是動(dòng)態(tài)生成目標(biāo)類的動(dòng)態(tài)代理類,根本不需要為每一個(gè)只需要定義一個(gè)動(dòng)態(tài)代理類,就可以代理所有、無(wú)數(shù)的真實(shí)類;當(dāng)然我們需要一個(gè)類來(lái)實(shí)現(xiàn)InvocationHandler接口即可。也就是說(shuō)我們只需要一個(gè)類即可。
java中提供了一個(gè)接口InvocationHandler和Proxy類來(lái)實(shí)現(xiàn)動(dòng)態(tài)代理。
InvocationHandler接口是代理實(shí)例用來(lái)調(diào)用處理程序(代理行為)的接口,它只有一個(gè)方法。接收的參數(shù)為:動(dòng)態(tài)代理對(duì)象,代理對(duì)象調(diào)用的接口方法的實(shí)例,執(zhí)行參數(shù)。
就如下面的Market類實(shí)現(xiàn)了InvocationHandler接口,內(nèi)部的Object target用來(lái)持有動(dòng)態(tài)代理的真實(shí)對(duì)象實(shí)例,bind方法用來(lái)接收外部真實(shí)類對(duì)象傳遞給target。然后重點(diǎn)就是重寫invoke方法了,這個(gè)方法和下面的Proxy類一起講解。
這個(gè)類是用來(lái)處理動(dòng)態(tài)代理的邏輯的,它的作用是接收生成的動(dòng)態(tài)代理對(duì)象和被代理對(duì)象實(shí)現(xiàn)的接口與運(yùn)行時(shí)的參數(shù),這樣就能攔截對(duì)接口方法的調(diào)用,從而實(shí)現(xiàn)自己的攔截邏輯。
如下圖,我們?cè)跍y(cè)試類中,使用Proxy類的newProxyInstance靜態(tài)方法來(lái)生成動(dòng)態(tài)代理對(duì)象。該方法很重要,傳入的參數(shù):被代理類的類加載器,被代理類的所實(shí)現(xiàn)的接口(用數(shù)組保存的),實(shí)現(xiàn)了InvocationHandler的接口的動(dòng)態(tài)代理處理類。
這個(gè)類用來(lái)生成了動(dòng)態(tài)代理的對(duì)象,很神奇的是,我們調(diào)用接口的方法時(shí),就發(fā)現(xiàn)方法被攔截了,這時(shí)候生成的是動(dòng)態(tài)代理對(duì)象,所以接口方法的邏輯已經(jīng)是被攔截的邏輯了。(這里我們看成是一個(gè)新的動(dòng)態(tài)代理的對(duì)象就好了)
為避免混亂,將包、類的結(jié)構(gòu)給出:
動(dòng)態(tài)代理類的命名規(guī)則:包名+$Proxy+id,同一個(gè)接口的實(shí)現(xiàn)類的id是相同的。
JDK動(dòng)態(tài)代理的總結(jié)(不足)1.JDK動(dòng)態(tài)代理是通過(guò)接口中的方法名,在動(dòng)態(tài)生成的代理類中調(diào)用業(yè)務(wù)實(shí)現(xiàn)類的同名方法。因此,對(duì)一個(gè)類而言,如果想要對(duì)它使用JDK動(dòng)態(tài)代理,那么這個(gè)類就必須實(shí)現(xiàn)接口interface,并且我們攔截的是其接口聲明的方法才行。簡(jiǎn)言之,JDK動(dòng)態(tài)代理只能對(duì)實(shí)現(xiàn)了接口的類生成代理,而不能針對(duì)未實(shí)現(xiàn)接口的類。
2.我們發(fā)現(xiàn),在JDK動(dòng)態(tài)代理的實(shí)現(xiàn)過(guò)程中,我們無(wú)法對(duì)接口中的各個(gè)方法都實(shí)現(xiàn)一段獨(dú)有的邏輯(如果被代理類實(shí)現(xiàn)的接口有多個(gè)方法,我們的動(dòng)態(tài)代理的攔截邏輯卻只有一段,所有的方法被攔截時(shí)都是用相同的邏輯來(lái)處理)。這是一個(gè)很大的問(wèn)題。
3.JDK動(dòng)態(tài)代理生成的動(dòng)態(tài)代理類,是無(wú)法調(diào)用原業(yè)務(wù)類自己擁有的方法的(即接口中沒(méi)有聲明的方法)。要明白,動(dòng)態(tài)代理類的存在意義是為了攔截方法并修改邏輯;而JDK動(dòng)態(tài)代理的局限性之一就是只能攔截接口所聲明的方法。
4.JDK動(dòng)態(tài)代理是利用反射機(jī)制生成一個(gè)實(shí)現(xiàn)代理接口的匿名類,在調(diào)用具體方法前調(diào)用InvokeHandler來(lái)處理。
3、CGLib動(dòng)態(tài)代理和JDK動(dòng)態(tài)代理不同的是,CGLib動(dòng)態(tài)代理解決了JDK動(dòng)態(tài)代理的第一個(gè)不足。也就是說(shuō),如果一個(gè)類沒(méi)有實(shí)現(xiàn)接口,那么我們還可以使用CGLib來(lái)生成其動(dòng)態(tài)代理對(duì)象。
這里我們要講到MethodInterceptor接口了。注意,CGLib動(dòng)態(tài)代理并不是JDK中的類,它是外部的lib包。
我們還需要結(jié)合動(dòng)態(tài)代理對(duì)象的生成來(lái)講解。
同樣,我們只需要定義一個(gè)動(dòng)態(tài)代理的處理類即可。實(shí)現(xiàn)了MethodInterceptor接口的類,需要重寫intercept方法,用來(lái)攔截被代理類的方法調(diào)用。然后在該類中定義一個(gè)生產(chǎn)動(dòng)態(tài)代理對(duì)象的方法,該方法接收被代理類的對(duì)象,然后攔截方法,設(shè)置調(diào)用攔截方法的邏輯,最后返回創(chuàng)建的動(dòng)態(tài)代理對(duì)象。
CGLib動(dòng)態(tài)代理的總結(jié)1.CGlib動(dòng)態(tài)代理的原理是通過(guò)繼承業(yè)務(wù)類,生成的動(dòng)態(tài)代理類是業(yè)務(wù)類的子類,通過(guò)重寫業(yè)務(wù)方法進(jìn)行代理。 因?yàn)閯?dòng)態(tài)代理類是繼承自業(yè)務(wù)類,所以該類和方法不能聲明成final(無(wú)法繼承或重寫)。
2.同JDK動(dòng)態(tài)代理一樣,CGLib動(dòng)態(tài)代理也無(wú)法做到對(duì)業(yè)務(wù)類的每個(gè)方法都實(shí)現(xiàn)不同的攔截邏輯。
JDK動(dòng)態(tài)代理和CGLib動(dòng)態(tài)代理的比較1.JDK動(dòng)態(tài)代理是面向接口,在創(chuàng)建代理實(shí)現(xiàn)類時(shí)比CGLib要快,創(chuàng)建動(dòng)態(tài)代理類的速度快。
2.CGLib動(dòng)態(tài)代理是通過(guò)字節(jié)碼底層繼承要代理類來(lái)實(shí)現(xiàn)(如果被代理類被final關(guān)鍵字所修飾,那么會(huì)失敗),在創(chuàng)建代理這一塊沒(méi)有JDK動(dòng)態(tài)代理快,但是運(yùn)行速度比JDK動(dòng)態(tài)代理要快。
3.2者最終都是生成了一個(gè)新的動(dòng)態(tài)代理類對(duì)象。
Spring中的動(dòng)態(tài)代理 1、Spring在選擇用JDK還是CGLiB的依據(jù)?(1)當(dāng)Bean實(shí)現(xiàn)接口時(shí),Spring就會(huì)用JDK的動(dòng)態(tài)代理。
(2)當(dāng)Bean沒(méi)有實(shí)現(xiàn)接口時(shí),Spring使用CGlib實(shí)現(xiàn)。
(3)可以強(qiáng)制使用CGlib(在spring配置中加入
(1)在對(duì)JDK動(dòng)態(tài)代理與CGlib動(dòng)態(tài)代理的代碼實(shí)驗(yàn)中看,1W次執(zhí)行下,JDK7及8的動(dòng)態(tài)代理性能比CGlib要好20%左右。
(2)使用CGLib實(shí)現(xiàn)動(dòng)態(tài)代理,CGLib底層采用ASM字節(jié)碼生成框架,使用字節(jié)碼技術(shù)生成代理類,比使用Java反射效率要高。唯一需要注意的是,CGLib不能對(duì)聲明為final的方法進(jìn)行代理,因?yàn)镃GLib原理是動(dòng)態(tài)生成被代理類的子類。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/77268.html
摘要:代理模式代理模式通俗一點(diǎn)的解釋就是在操作一個(gè)對(duì)象和對(duì)象中的方法時(shí),不是直接操作這個(gè)對(duì)象,還是通過(guò)一個(gè)代理對(duì)象來(lái)操作這個(gè)實(shí)際的目標(biāo)對(duì)象。 代理模式: 代理模式通俗一點(diǎn)的解釋就是在操作一個(gè)對(duì)象和對(duì)象中的方法時(shí),不是直接操作這個(gè)對(duì)象,還是通過(guò)一個(gè)代理對(duì)象來(lái)操作這個(gè)實(shí)際的目標(biāo)對(duì)象。應(yīng)用場(chǎng)景一般是需要在執(zhí)行某個(gè)已經(jīng)寫好的方法前后再添加一段邏輯,比如執(zhí)行方法前打印日志,或者在執(zhí)行方法之前和之后打時(shí)...
摘要:代理模式從類型上來(lái)說(shuō),可以分為靜態(tài)代理和動(dòng)態(tài)代理兩種類型。然而今天的重點(diǎn)是我們都知道牛逼轟轟的的實(shí)現(xiàn)的一種方式是使用的動(dòng)態(tài)代理另一種是,大部分人也會(huì)用的動(dòng)態(tài)代理,不過(guò)沒(méi)有研究過(guò)的動(dòng)態(tài)代理到底是怎么實(shí)現(xiàn)的。 動(dòng)態(tài)代理 代理模式是設(shè)計(jì)模式中非常重要的一種類型,而設(shè)計(jì)模式又是編程中非常重要的知識(shí)點(diǎn),特別是在業(yè)務(wù)系統(tǒng)的重構(gòu)中,更是有舉足輕重的地位。代理模式從類型上來(lái)說(shuō),可以分為靜態(tài)代理和動(dòng)態(tài)代...
Java的三種代理模式 參考:http://www.cnblogs.com/cenyu/...Java核心技術(shù)原書第九版6.5節(jié) 為什么使用代理 我們?cè)趯懸粋€(gè)功能函數(shù)時(shí),經(jīng)常需要在其中寫入與功能不是直接相關(guān)但很有必要的代 碼,如日志記錄,信息發(fā)送,安全和事務(wù)支持等,這些枝節(jié)性代碼雖然是必要的,但它會(huì)帶來(lái)以下麻煩: 枝節(jié)性代碼游離在功能性代碼之外,它不是函數(shù)的目的,這是對(duì)OO是一種破壞 枝節(jié)性...
摘要:定義代理設(shè)計(jì)模式為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。動(dòng)態(tài)代理代理類在程序運(yùn)行時(shí)創(chuàng)建的代理方式被成為動(dòng)態(tài)代理。 1.定義 代理設(shè)計(jì)模式:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。動(dòng)態(tài)代理:代理類在程序運(yùn)行時(shí)創(chuàng)建的代理方式被成為 動(dòng)態(tài)代理。代理類并不是在Java代碼中定義的,而而是在運(yùn)行時(shí)根據(jù)我們?cè)贘ava代碼中的指示動(dòng)態(tài)生成的 2.簡(jiǎn)介 Sping mvc的Aop就是基于動(dòng)...
摘要:話說(shuō)誰(shuí)還干類似的事,就在文章末尾點(diǎn)個(gè)贊代銷店等其實(shí)就是現(xiàn)在的商店,以前小的時(shí)候聽家鄉(xiāng)人叫代銷店,也是一種代理模式??梢哉f(shuō)是系統(tǒng)中最重要的架構(gòu)之一。 showImg(https://segmentfault.com/img/remote/1460000012278678?w=1240&h=469); PS:轉(zhuǎn)載請(qǐng)注明出處作者: TigerChain地址: http://www.jians...
閱讀 1591·2021-11-24 11:16
閱讀 2859·2021-07-28 12:32
閱讀 2393·2019-08-30 11:22
閱讀 1500·2019-08-30 11:01
閱讀 676·2019-08-29 16:24
閱讀 3622·2019-08-29 12:52
閱讀 1694·2019-08-29 12:15
閱讀 1398·2019-08-29 11:18