日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java动态代理的两种实现方法:JDK动态代理和CGLIB动态代理

發(fā)布時(shí)間:2024/10/8 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java动态代理的两种实现方法:JDK动态代理和CGLIB动态代理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Java動態(tài)代理的兩種實(shí)現(xiàn)方法:JDK動態(tài)代理和CGLIB動態(tài)代理

  • 代理模式
  • JDK動態(tài)代理
  • CGLIB動態(tài)代理

代理模式

  • 代理模式是23種設(shè)計(jì)模式的一種,指一個(gè)對象A通過持有另一個(gè)對象B,可以具有B同樣的行為的模式。為了對外開放協(xié)議,B往往實(shí)現(xiàn)了一個(gè)接口,A也會去實(shí)現(xiàn)接口。但B是真正的實(shí)現(xiàn)類,A則比較“虛”,A借用了B的方法去實(shí)現(xiàn)接口的方法。A雖然為“偽軍”,但它可以增強(qiáng)B,在調(diào)用B的方法前后都做些其他的事情。Spring AOP就是使用了動態(tài)代理完成了代碼的動態(tài)植入。
  • 使用動態(tài)代理的好處還不止這些,一個(gè)工程如果依賴另一個(gè)工程給的接口,但是另一個(gè)工程的接口不穩(wěn)定,經(jīng)常變更協(xié)議,就可以使用一個(gè)代理,接口變更時(shí),只需要修改代理,不需要修改業(yè)務(wù)代碼。從這個(gè)意義上說,所有調(diào)外界的接口,我們都可以這么做,不讓外界的代碼對我們的代碼有侵入,這叫防御式編程。
  • 上述例子中,類A寫死持有B,就是B的靜態(tài)代理。如果A代理的對象是不確定的,就是動態(tài)代理。動態(tài)代理目前有兩種常見的實(shí)現(xiàn),JDK動態(tài)代理和CGLIB動態(tài)代理。

JDK動態(tài)代理

JDK動態(tài)代理是JRE提供的類庫,可以直接使用,不依賴第三方。先看一下JDK動態(tài)代理的使用代碼,在理解原理。

首先,有個(gè)明星接口,有唱和跳兩個(gè)方法。

package proxy;public interface Star {String sing(String name);String dance(String name); }

再有一個(gè)明星實(shí)現(xiàn)類-劉德華。

package proxy;public class LiuDeHua implements Star {public String sing(String name) {System.out.println("給我一杯忘情水!");return "唱完";}public String dance(String name) {System.out.println("開心的馬騮");return "跳完";} }

明星演出前需要有人收錢,由于要準(zhǔn)備演出,自己不做這個(gè)工作,一般交給一個(gè)經(jīng)紀(jì)人。便于理解,它的名字以Proxy結(jié)尾,但他不是代理類,原因是它沒有實(shí)現(xiàn)我們的明星接口,無法對外服務(wù),它僅僅是一個(gè)wrapper。

package proxy;import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;public class StarProxy implements InvocationHandler {//目標(biāo)類,被代理對象private Object target;public void setTarget(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//這里可以做增強(qiáng)System.out.println("收錢");Object result = method.invoke(target, args);return result;}//生成代理類public Object CreateProxyedObj() {return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);} }

上述例子中,方法CreatProxyedObj返回的對象才是我們的代理類,它需要三個(gè)參數(shù),前兩個(gè)參數(shù)的意思是在同一個(gè)classloader下通過接口創(chuàng)建出一個(gè)對象,該對象需要一個(gè)屬性,也就是第三個(gè)參數(shù),它是一個(gè)InvocationHandler。需要注意的是這個(gè)CreatProxyedObj方法不一定非得在我們的StarProxy類中,往往放在一個(gè)工廠類中。上述代理的代碼使用過程一般如下:

1、new一個(gè)目標(biāo)對象

2、new一個(gè)InvocationHandler,將目標(biāo)對象set進(jìn)去

3、通過CreatProxyedObj創(chuàng)建代理對象,強(qiáng)轉(zhuǎn)為目標(biāo)對象的接口類型即可使用,實(shí)際上生成的代理對象實(shí)現(xiàn)了目標(biāo)接口。

package proxy;public class Client {public static void main(String[] args) {Star ldh = new LiuDeHua();StarProxy proxy = new StarProxy();proxy.setTarget(ldh);Star proxyedObj = (Star) proxy.CreateProxyedObj();proxyedObj.sing("劉德華");} }

Proxy(jdk類庫提供)根據(jù)B的接口生成一個(gè)實(shí)現(xiàn)類,我們成為C,它就是動態(tài)代理類(該類型是 $Proxy+數(shù)字 的“新的類型”)。生成過程是:由于拿到了接口,便可以獲知接口的所有信息(主要是方法的定義),也就能聲明一個(gè)新的類型去實(shí)現(xiàn)該接口的所有方法,這些方法顯然都是“虛”的,它調(diào)用另一個(gè)對象的方法。當(dāng)然這個(gè)被調(diào)用的對象不能是對象B,如果是對象B,我們就沒法增強(qiáng)了,等于饒了一圈又回來了。

所以它調(diào)用的是B的包裝類,這個(gè)包裝類需要我們來實(shí)現(xiàn),但是jdk給出了約束,它必須實(shí)現(xiàn)InvocationHandler,上述例子中就是StarProxy, 這個(gè)接口里面有個(gè)方法,它是所有Target的所有方法的調(diào)用入口(invoke),調(diào)用之前我們可以加自己的代碼增強(qiáng)。

看下我們的實(shí)現(xiàn),我們在InvocationHandler里調(diào)用了對象B(target)的方法,調(diào)用之前增強(qiáng)了B的方法。

@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable{// 這里增強(qiáng)System.out.println("收錢");Object result = method.invoke(target, args);return result;}

所以可以這么認(rèn)為C代理了InvocationHandler,InvocationHandler代理了我們的類B,兩級代理。

整個(gè)JDK動態(tài)代理的秘密也就這些,簡單一句話,動態(tài)代理就是要生成一個(gè)包裝類對象,由于代理的對象是動態(tài)的,所以叫動態(tài)代理。由于我們需要增強(qiáng),這個(gè)增強(qiáng)是需要留給開發(fā)人員開發(fā)代碼的,因此代理類不能直接包含被代理對象,而是一個(gè)InvocationHandler,該InvocationHandler包含被代理對象,并負(fù)責(zé)分發(fā)請求給被代理對象,分發(fā)前后均可以做增強(qiáng)。從原理可以看出,JDK動態(tài)代理是“對象”的代理。

CGLIB動態(tài)代理

代理的目的是構(gòu)造一個(gè)和被代理的對象有同樣行為的對象,一個(gè)對象的行為是在類中定義的,對象只是類的實(shí)例。所以構(gòu)造代理,不一定非得通過持有包裝對象這一方式。

通過繼承可以繼承父類所有得公開方法,然后可以重寫這些方法,在重寫時(shí)對這些方法增強(qiáng),這就是CGLIB的思想。根據(jù)里氏代換原則(LSP),父類需要出現(xiàn)的地方,子類可以出現(xiàn),所以CGLIB實(shí)現(xiàn)的代理也是可以被正常使用的。

package proxy;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy;public class CglibProxy implements MethodInterceptor {// 根據(jù)一個(gè)類型產(chǎn)生代理類,此方法不要求一定放在MethodInterceptor中public Object CreatProxyedObj(Class<?> clazz){Enhancer enhancer = new Enhancer();enhancer.setSuperclass(clazz);enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable{// 這里增強(qiáng)System.out.println("收錢");return arg3.invokeSuper(arg0, arg2);} }

從代碼可以看出,它和jdk動態(tài)代理有所不同,對外表現(xiàn)上看CreatProxyedObj,它只需要一個(gè)類型clazz就可以產(chǎn)生一個(gè)代理對象, 所以說是“類的代理”,且創(chuàng)造的對象通過打印類型發(fā)現(xiàn)也是一個(gè)新的類型。不同于jdk動態(tài)代理,jdk動態(tài)代理要求對象必須實(shí)現(xiàn)接口(三個(gè)參數(shù)的第二個(gè)參數(shù)),cglib對此沒有要求。

cglib的原理是這樣,它生成一個(gè)繼承B的類型C(代理類),這個(gè)代理類持有一個(gè)MethodInterceptor,我們setCallback時(shí)傳入的。 C重寫所有B中的方法(方法名一致),然后在C中,構(gòu)建名叫“CGLIB”+“父類方法名父類方法名”的方法(下面叫cglib方法,所有非private的方法都會被構(gòu)建),方法體里只有一句話super.方法名(),可以簡單的認(rèn)為保持了對父類方法的一個(gè)引用,方便調(diào)用。

這樣的話,C中就有了重寫方法、cglib方法、父類方法(不可見),還有一個(gè)統(tǒng)一的攔截方法(增強(qiáng)方法intercept)。其中重寫方法和cglib方法肯定是有映射關(guān)系的。

C的重寫方法是外界調(diào)用的入口(LSP原則),它調(diào)用MethodInterceptor的intercept方法,調(diào)用時(shí)會傳遞四個(gè)參數(shù),第一個(gè)參數(shù)傳遞的是this,代表代理類本身,第二個(gè)參數(shù)標(biāo)示攔截的方法,第三個(gè)參數(shù)是入?yún)?#xff0c;第四個(gè)參數(shù)是cglib方法,intercept方法完成增強(qiáng)后,我們調(diào)用cglib方法間接調(diào)用父類方法完成整個(gè)方法鏈的調(diào)用。

與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的Java动态代理的两种实现方法:JDK动态代理和CGLIB动态代理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线免费国产 | 欧美另类videos| 三级黄色图片 | 操天天| 综合色播 | 国产成人av网| 怡红院成永久免费人全部视频 | 黄色片www| 日本黄色三级网站 | 黄色激情小说视频 | 日本久久一区 | 色婷婷国产精品久久包臀 | 天天艹日日艹 | 亚洲中字在线 | 波多野结衣在线观看一区二区三区 | 福利在线视频观看 | 国产精品视频网址 | 按摩ⅹxxx性hd中国 | 李华月全部毛片 | 国产三级一区二区三区 | 国产美女在线免费 | 日本在线观看一区二区三区 | 中文字幕精品一区二区精品 | 少妇av一区二区三区无码 | 伊人网视频在线观看 | 依人成人 | 五月天av网站 | 亚洲成人午夜影院 | 婷婷亚洲视频 | 五月婷婷小说 | 无码国产69精品久久久久网站 | 国产精品 欧美精品 | 芒果视频污污 | 特级淫片裸体免费看冫 | 亚洲国产福利视频 | 一区二区三区四区五区av | 在线免费观看视频你懂的 | 免费欧美日韩 | 波多野结衣一区 | 成人中文视频 | 国产福利免费观看 | 亚洲精品国产熟女久久久 | 激情视频网站 | 亚洲AV无码AV吞精久久中文版 | 亚洲av无码国产精品久久不卡 | 公车激情云雨小说 | 疯狂做受xxxx国产 | 国产日韩欧美精品在线观看 | 色丁香六月 | 四色成人av永久网址 | 国产精品久久久久久久久晋中 | 成年人在线免费观看视频网站 | 一区二区国产在线 | 潘金莲激情呻吟欲求不满视频 | 精品综合网 | 91看大片| 国产日韩一区二区 | 国产一级网站 | 日本大尺度激情做爰hd | 国产精品99久久久精品无码 | 中文字幕日韩精品一区 | 国产综合久久久久 | 日本人妻一区二区三区 | 风间由美一区 | 一本一本久久a久久精品综合麻豆 | 亚洲4p| 国产福利一区在线观看 | 成人深夜小视频 | 搞黄视频在线观看 | 免费的三级网站 | 汗汗视频 | 日韩免费一区二区三区 | 在线观看免费视频一区二区 | 日韩最新在线 | 国产一区二区三区视频免费观看 | 日韩美女网站 | 99热伊人| 在线免费一级片 | 粗喘呻吟撞击猛烈疯狂 | 黄色片免费网站 | 天天综合网久久综合网 | 一区二区三区麻豆 | 插插久久 | 综合色久 | 四月婷婷| av中出在线 | 日韩av大片在线观看 | 久久99精品国产麻豆婷婷 | 国产chinesehd天美传媒 | 91精品国产高清一区二区三区蜜臀 | 久久久99精品国产一区二区三区 | 韩国中文字幕在线观看 | 超碰狠狠 | 国产精品视频免费 | 成人影音在线 | 91国内在线视频 | 日韩久久影视 | 97超视频在线观看 | av最新地址 |