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