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

歡迎訪問 生活随笔!

生活随笔

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

java

Java基础-JDK动态代理

發(fā)布時(shí)間:2025/4/14 java 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java基础-JDK动态代理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

JDK的動(dòng)態(tài)代理依靠接口實(shí)現(xiàn)

?代理模式?
代理模式是常用的java設(shè)計(jì)模式,他的特征是代理類與委托類有同樣的接口,代理類主要負(fù)責(zé)為委托類預(yù)處理消息、過濾消息、把消息轉(zhuǎn)發(fā)給委托類,以及事后處理消息等。代理類與委托類之間通常會(huì)存在關(guān)聯(lián)關(guān)系,一個(gè)代理類的對(duì)象與一個(gè)委托類的對(duì)象關(guān)聯(lián),代理類的對(duì)象本身并不真正實(shí)現(xiàn)服務(wù),而是通過調(diào)用委托類的對(duì)象的相關(guān)方法,來(lái)提供特定的服務(wù)。?

?

?

在java的動(dòng)態(tài)代理機(jī)制中,有兩個(gè)重要的類或接口,一個(gè)是 InvocationHandler(Interface)、另一個(gè)則是 Proxy(Class),這一個(gè)類和接口是實(shí)現(xiàn)我們動(dòng)態(tài)代理所必須用到的.

InvocationHandler

每一個(gè)動(dòng)態(tài)代理類都必須要實(shí)現(xiàn)InvocationHandler這個(gè)接口,并且每個(gè)代理類的實(shí)例都關(guān)聯(lián)到了一個(gè)handler,當(dāng)我們通過代理對(duì)象調(diào)用一個(gè)方法的時(shí)候,這個(gè)方法的調(diào)用就會(huì)被轉(zhuǎn)發(fā)為由InvocationHandler這個(gè)接口的 invoke 方法來(lái)進(jìn)行調(diào)用。我們來(lái)看看InvocationHandler這個(gè)接口的唯一一個(gè)方法?invoke?方法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable方法一共接受三個(gè)參數(shù) proxy:  指代我們所代理的那個(gè)真實(shí)對(duì)象 method:  指代的是我們所要調(diào)用真實(shí)對(duì)象的某個(gè)方法的Method對(duì)象 args:  指代的是調(diào)用真實(shí)對(duì)象某個(gè)方法時(shí)接受的參數(shù)

?

?

?

Proxy

Proxy這個(gè)類的作用就是用來(lái)動(dòng)態(tài)創(chuàng)建一個(gè)代理對(duì)象的類,它提供了許多的方法,但是我們用的最多的就是?newProxyInstance?這個(gè)方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException作用就是得到一個(gè)動(dòng)態(tài)的代理對(duì)象,其接收三個(gè)參數(shù) loader:  一個(gè)ClassLoader對(duì)象,定義了由哪個(gè)ClassLoader對(duì)象來(lái)對(duì)生成的代理對(duì)象進(jìn)行加載 interfaces:  一個(gè)Interface對(duì)象的數(shù)組,表示的是我將要給我需要代理的對(duì)象提供一組什么接口,如果我提供了一組接口給它,那么這個(gè)代理對(duì)象就宣稱實(shí)現(xiàn)了該接口(多態(tài)),這樣我就能調(diào)用這組接口中的方法了 h:  一個(gè)InvocationHandler對(duì)象,表示的是當(dāng)我這個(gè)動(dòng)態(tài)代理對(duì)象在調(diào)用方法的時(shí)候,會(huì)關(guān)聯(lián)到哪一個(gè)InvocationHandler對(duì)象上

?

?

?

通過實(shí)例理解動(dòng)態(tài)代理

首先定義一個(gè)類接口

public interface Subject {public void rent();public void hello(String str); }

?

接著,定義了一個(gè)類來(lái)實(shí)現(xiàn)這個(gè)接口,這個(gè)類就是我們的真實(shí)對(duì)象:

public class RealSubject implements Subject {@Overridepublic void rent(){System.out.println("I want to rent my house");}@Overridepublic void hello(String str){System.out.println("hello: " + str);} }

下一步,定義一個(gè)動(dòng)態(tài)代理類了,前面說(shuō)個(gè),每一個(gè)動(dòng)態(tài)代理類都必須要實(shí)現(xiàn) InvocationHandler 這個(gè)接口,因此我們這個(gè)動(dòng)態(tài)代理類也不例外:

public class DynamicProxy implements InvocationHandler {// 這個(gè)就是我們要代理的真實(shí)對(duì)象private Object subject;// 構(gòu)造方法,給我們要代理的真實(shí)對(duì)象賦初值public DynamicProxy(Object subject){this.subject = subject;}@Overridepublic Object invoke(Object object, Method method, Object[] args)throws Throwable{//在代理真實(shí)對(duì)象前我們可以添加一些自己的操作System.out.println("before rent house");System.out.println("Method:" + method);//當(dāng)代理對(duì)象調(diào)用真實(shí)對(duì)象的方法時(shí),其會(huì)自動(dòng)的跳轉(zhuǎn)到代理對(duì)象關(guān)聯(lián)的handler對(duì)象的invoke方法來(lái)進(jìn)行調(diào)用 method.invoke(subject, args);//在代理真實(shí)對(duì)象后我們也可以添加一些自己的操作System.out.println("after rent house");return null;}}

?

最后,來(lái)看看我們的Client類:

public class Client {public static void main(String[] args){// 我們要代理的真實(shí)對(duì)象Subject realSubject = new RealSubject();// 我們要代理哪個(gè)真實(shí)對(duì)象,就將該對(duì)象傳進(jìn)去,最后是通過該真實(shí)對(duì)象來(lái)調(diào)用其方法的InvocationHandler handler = new DynamicProxy(realSubject);/** 通過Proxy的newProxyInstance方法來(lái)創(chuàng)建我們的代理對(duì)象,我們來(lái)看看其三個(gè)參數(shù)* 第一個(gè)參數(shù) handler.getClass().getClassLoader() ,我們這里使用handler這個(gè)類的ClassLoader對(duì)象來(lái)加載我們的代理對(duì)象* 第二個(gè)參數(shù)realSubject.getClass().getInterfaces(),我們這里為代理對(duì)象提供的接口是真實(shí)對(duì)象所實(shí)行的接口,表示我要代理的是該真實(shí)對(duì)象,這樣我就能調(diào)用這組接口中的方法了* 第三個(gè)參數(shù)handler, 我們這里將這個(gè)代理對(duì)象關(guān)聯(lián)到了上方的 InvocationHandler 這個(gè)對(duì)象上*/Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);System.out.println(subject.getClass().getName());subject.rent();subject.hello("world");} }

控制臺(tái)的輸出:

$Proxy0before rent house Method:public abstract void com.xiaoluo.dynamicproxy.Subject.rent() I want to rent my house after rent housebefore rent house Method:public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String) hello: world after rent house

?

我們首先來(lái)看看?$Proxy0 這東西,我們看到,這個(gè)東西是由

System.out.println(subject.getClass().getName());

?

這條語(yǔ)句打印出來(lái)的,那么為什么我們返回的這個(gè)代理對(duì)象的類名是這樣的呢?

Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);

可能我以為返回的這個(gè)代理對(duì)象會(huì)是Subject類型的對(duì)象,或者是InvocationHandler的對(duì)象,結(jié)果卻不是,首先我們解釋一下為什么我們這里可以將其轉(zhuǎn)化為Subject類型的對(duì)象?原因就是在newProxyInstance這個(gè)方法的第二個(gè)參數(shù)上,我們給這個(gè)代理對(duì)象提供了一組什么接口,那么我這個(gè)代理對(duì)象就會(huì)實(shí)現(xiàn)了這組接口,這個(gè)時(shí)候我們當(dāng)然可以將這個(gè)代理對(duì)象強(qiáng)制類型轉(zhuǎn)化為這組接口中的任意一個(gè),因?yàn)檫@里的接口是Subject類型,所以就可以將其轉(zhuǎn)化為Subject類型了。

同時(shí)我們一定要記住,通過?Proxy.newProxyInstance 創(chuàng)建的代理對(duì)象是在jvm運(yùn)行時(shí)動(dòng)態(tài)生成的一個(gè)對(duì)象,它并不是我們的InvocationHandler類型,也不是我們定義的那組接口的類型,而是在運(yùn)行是動(dòng)態(tài)生成的一個(gè)對(duì)象,并且命名方式都是這樣的形式,以$開頭,proxy為中,最后一個(gè)數(shù)字表示對(duì)象的標(biāo)號(hào)

接著我們來(lái)看看這兩句?

subject.rent(); subject.hello("world");

?

這里是通過代理對(duì)象來(lái)調(diào)用實(shí)現(xiàn)的那種接口中的方法,這個(gè)時(shí)候程序就會(huì)跳轉(zhuǎn)到由這個(gè)代理對(duì)象關(guān)聯(lián)到的 handler 中的invoke方法去執(zhí)行,而我們的這個(gè) handler 對(duì)象又接受了一個(gè) RealSubject類型的參數(shù),表示我要代理的就是這個(gè)真實(shí)對(duì)象,所以此時(shí)就會(huì)調(diào)用 handler 中的invoke方法去執(zhí)行:

public Object invoke(Object object, Method method, Object[] args)throws Throwable{//  在代理真實(shí)對(duì)象前我們可以添加一些自己的操作System.out.println("before rent house");System.out.println("Method:" + method);// 當(dāng)代理對(duì)象調(diào)用真實(shí)對(duì)象的方法時(shí),其會(huì)自動(dòng)的跳轉(zhuǎn)到代理對(duì)象關(guān)聯(lián)的handler對(duì)象的invoke方法來(lái)進(jìn)行調(diào)用 method.invoke(subject, args);//  在代理真實(shí)對(duì)象后我們也可以添加一些自己的操作System.out.println("after rent house");return null;}

我們看到,在真正通過代理對(duì)象來(lái)調(diào)用真實(shí)對(duì)象的方法的時(shí)候,我們可以在該方法前后添加自己的一些操作,同時(shí)我們看到我們的這個(gè) method 對(duì)象是這樣的:

public abstract void com.xiaoluo.dynamicproxy.Subject.rent()public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)

正好就是我們的Subject接口中的兩個(gè)方法,這也就證明了當(dāng)我通過代理對(duì)象來(lái)調(diào)用方法的時(shí)候,起實(shí)際就是委托由其關(guān)聯(lián)到的 handler 對(duì)象的invoke方法中來(lái)調(diào)用,并不是自己來(lái)真實(shí)調(diào)用,而是通過代理的方式來(lái)調(diào)用的。

這就是我們的java動(dòng)態(tài)代理機(jī)制

?

?

?

?

?

?

?

?

?

?

?

所謂Dynamic Proxy是這樣一種class:它是在運(yùn)行時(shí)生成的class,在生成它時(shí)你必須提供一 組interface給它,然后該class就宣稱它實(shí)現(xiàn)了這些 interface。你當(dāng)然可以把該class的實(shí) 例當(dāng)作這些interface中的任何一個(gè)來(lái)用。當(dāng)然啦,這個(gè)Dynamic Proxy其實(shí)就是一個(gè)Proxy, 它不會(huì)替你作實(shí)質(zhì)性的工作,在生成它的實(shí)例時(shí)你必須提供一個(gè)handler,由它接管實(shí)際的工 作。

?

java動(dòng)態(tài)代理類位于java.lang.reflect包下,一般主要涉及到以下兩個(gè)類:

Interface InvocationHandler
  
該接口中僅定義了一個(gè)方法Object:invoke(Object obj,Method method, Object[] args)。在實(shí)際使用時(shí),第一個(gè)參數(shù)obj一般是指代理 類,method是被代理的方法,如上例中的request(),args為該方法的參數(shù)數(shù)組。 這個(gè)抽 象方法在代理類中動(dòng)態(tài)實(shí)現(xiàn)。
Proxy
  該類即為動(dòng)態(tài)代理類,作用類似于上例中的ProxySubject。
Protected Proxy(InvocationHandler h)
  構(gòu)造函數(shù),估計(jì)用于給內(nèi)部的h賦值。
Static Class getProxyClass (ClassLoader loader, Class[] interfaces)
  獲得一個(gè) 代理類,其中l(wèi)oader是類裝載器,interfaces是真實(shí)類所擁有的全部接口的數(shù)組。
Static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
  返回代理類的一個(gè)實(shí)例,返回后的代理類可以當(dāng)作被代理類使用 (可使用被代理類的在Subject接口中聲明過的方法)。

?

在使用動(dòng)態(tài)代理類時(shí),我們必須實(shí)現(xiàn)InvocationHandler接口,以第一節(jié)中的示例為例:

// 抽象角色(之前是抽象類,此處應(yīng)改為接口): public interface Subject {abstract public void request(); }// 具體角色RealSubject: public class RealSubject implements Subject {public RealSubject() {}public void request() {System.out.println( " From real subject. " );}}// 代理處理器: import java.lang.reflect.Method; import java.lang.reflect.InvocationHandler;public class DynamicSubject implements InvocationHandler {private Object sub;public DynamicSubject() {}public DynamicSubject(Object obj) {sub = obj;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println( " before calling " + method);method.invoke(sub,args);System.out.println( " after calling " + method);return null ;} }

?

?

該代理類的內(nèi)部屬性為Object類,實(shí)際使用時(shí)通過該類的構(gòu)造函數(shù)DynamicSubject(Object obj)對(duì)其賦值;此外,在該類還實(shí)現(xiàn)了invoke方法,該方法中的

method.invoke(sub,args);

?

其實(shí)就是調(diào)用被代理對(duì)象的將要被執(zhí)行的方法,方法參數(shù)sub是實(shí)際的被代理對(duì)象,args為執(zhí) 行被代理對(duì)象相應(yīng)操作所需的參數(shù)。通過動(dòng)態(tài)代理類,我們可以在調(diào)用之前或之后執(zhí)行一些 相關(guān)操作。

// 客戶端: import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; import java.lang.reflect.Constructor; import java.lang.reflect.Method;public class Client {static public void main(String[] args) throws Throwable {RealSubject rs = new RealSubject(); // 在這里指定被代理類InvocationHandler ds = new DynamicSubject(rs);Class cls = rs.getClass();// 以下是一次性生成代理Subject subject = (Subject) Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),ds );subject.request();} }// 程序運(yùn)行結(jié)果: before calling public abstract void Subject.request() From real subject. after calling public abstract void Subject.request()

?

通過這種方式,被代理的對(duì)象(RealSubject)可以在運(yùn)行時(shí)動(dòng)態(tài)改變,需要控制的接口 (Subject接口)可以在運(yùn)行時(shí)改變,控制的方式(DynamicSubject類)也可以動(dòng)態(tài)改變,從而實(shí) 現(xiàn)了非常靈活的動(dòng)態(tài)代理關(guān)系。

?

轉(zhuǎn)載于:https://www.cnblogs.com/hwaggLee/p/4499188.html

總結(jié)

以上是生活随笔為你收集整理的Java基础-JDK动态代理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 97在线观看视频 | 中文视频一区二区 | 三级伦理片 | 少妇高潮视频 | 久久成| 国产精品伦一区二区三区 | 中文字幕二区在线观看 | 中文字幕国产在线观看 | 激情草逼| 美美女高清毛片视频免费观看 | 日本公妇乱淫免费视频一区三区 | 日日撸视频 | 鲁鲁在线| 嫩草嫩草嫩草嫩草 | 91九色视频 | 脱美女衣服亲摸揉视频 | wwww黄色片 | 国产视频你懂得 | 四季av国产一区二区三区 | 香蕉视频亚洲一级 | 美女污污网站 | 午夜成人亚洲理伦片在线观看 | 爽爽窝窝午夜精品一区二区 | 另类激情亚洲 | 男女h网站| 美女草逼视频 | 欧美成人一区在线 | 国产自在线 | 天天艹av | 中文字幕一区二区三区免费 | 动漫大乳美女 | 91精品色| 精品动漫一区二区三区在线观看 | 干夜夜| 日本人妻熟妇久久久久久 | 国产精品成人国产乱一区 | 欧美在线视频第一页 | 玖玖爱在线精品视频 | 99热国产在线观看 | 欧美黑人孕妇孕交 | 国产原创在线观看 | 激情黄色av| 91第一页| 操操久久 | a天堂资源在线 | 亚洲一区二区三区在线视频 | 欧美日韩中文字幕在线播放 | 精品91久久久久久 | 精品在线小视频 | 亚洲国产一二 | 91超碰国产在线 | 99久久久无码国产精品不卡 | 牛牛影视免费观看 | 一区二区毛片 | 奇米狠狠777 | 超碰人人人人人人人 | 欧州一区二区 | 欧美一区二区视频在线观看 | 欧美xxxxxhd| 六月色| 欧美一区二区三区免费在线观看 | 亚洲宅男天堂 | 久久亚洲影视 | 日韩激情国产 | 看全黄大色黄大片 | 亚洲视频导航 | 国产123在线 | 我们俩电影网mp4动漫官网 | 亚洲啊v在线| 国产二级毛片 | 色婷婷久久综合中文久久蜜桃av | 天天摸夜夜操 | 婷婷色婷婷 | 三级做爰第一次 | 91在线精品秘密一区二区 | 刘亦菲久久免费一区二区 | 无码少妇一区二区 | 成人在线免费观看网站 | 欧美日韩日本国产 | 香蕉久久一区二区三区 | 伊人3| 国产粉嫩在线观看 | 亚洲精品国产精品乱码视色 | 亚洲色图18p | 久久亚洲伊人 | 国产自产视频 | 先锋资源一区二区 | 欧亚成人av | 亚洲av无码不卡一区二区三区 | 一区二区三区免费在线观看 | 精品视频第一页 | αv在线 | 伊人网成人网 | 久久一本精品 | 日本啪啪网站 | 韩国色网| 我们的2018中文免费看 | 免费观看视频一区二区 | 国产欧美一区二区精品忘忧草 |