黄色网址大全免费-黄色网址你懂得-黄色网址你懂的-黄色网址有那些-免费超爽视频-免费大片黄国产在线观看

專(zhuān)注Java教育14年 全國(guó)咨詢/投訴熱線:400-8080-105
動(dòng)力節(jié)點(diǎn)LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁(yè) 學(xué)習(xí)攻略 Java學(xué)習(xí) Java動(dòng)態(tài)代理的簡(jiǎn)介

Java動(dòng)態(tài)代理的簡(jiǎn)介

更新時(shí)間:2022-10-20 10:10:27 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1374次

Java 動(dòng)態(tài)代理類(lèi)是原始類(lèi)之上的一種“附加組件”,它允許Java 開(kāi)發(fā)人員根據(jù)需要更改原始類(lèi)的行為。假設(shè),如果您將一個(gè)類(lèi)用作現(xiàn)成JAR 庫(kù)的一部分,并且您不能簡(jiǎn)單地重寫(xiě)其源代碼,但您還需要更改該類(lèi)的行為方式。

例如,您不知道可以在您的對(duì)象上調(diào)用此類(lèi)的哪個(gè)方法,但您想輸出一個(gè)重要的“確認(rèn)”消息。Java 動(dòng)態(tài)代理是這個(gè)問(wèn)題的理想解決方案。

在本文中,我們將了解有關(guān) Java 動(dòng)態(tài)代理的所有信息。什么是 Java 動(dòng)態(tài)代理?他們是如何工作的?以及何時(shí)應(yīng)該在您的 Java 代碼中理想地使用它。

什么是 Java 動(dòng)態(tài)代理?

Java 動(dòng)態(tài)代理是 Java 代理設(shè)計(jì)模式的一部分。當(dāng)程序需要擴(kuò)展或修改現(xiàn)有類(lèi)的某些功能時(shí),它允許創(chuàng)建代理對(duì)象。在這種情況下,將實(shí)例化代理對(duì)象而不是原始對(duì)象。通常,代理對(duì)象具有與原始對(duì)象相同的方法,并且在 Java 代理類(lèi)中擴(kuò)展了原始類(lèi)。Java 動(dòng)態(tài)代理模式具有原始對(duì)象的句柄,并且也可以調(diào)用原始類(lèi)方法。

因此,代理類(lèi)可以以非常方便的方式實(shí)現(xiàn)很多不同的東西,這樣的事情很少有例子包括:

可以將日志記錄方法擴(kuò)展到原始類(lèi)以記錄方法何時(shí)啟動(dòng)和停止。

可以使用 Java 動(dòng)態(tài)代理對(duì)參數(shù)執(zhí)行額外的檢查。

代理類(lèi)也可用于在最終確定之前模擬原始類(lèi)的行為,以檢查它是否按預(yù)期執(zhí)行。

如果不修改類(lèi)的原始代碼,就無(wú)法完成上述應(yīng)用,這使得它們成為 Java 動(dòng)態(tài)代理的理想應(yīng)用。

在這樣的應(yīng)用程序中,代理類(lèi)不直接在原始類(lèi)對(duì)象上實(shí)現(xiàn)功能。遵循單一職責(zé)原則,代理類(lèi)只創(chuàng)建一個(gè)代理,并在處理程序中修改實(shí)際行為。當(dāng)調(diào)用代理對(duì)象而不是原始對(duì)象時(shí),Java 動(dòng)態(tài)代理將決定是否必須調(diào)用原始方法或處理程序。處理程序可以執(zhí)行其擴(kuò)展任務(wù),也可以調(diào)用原始方法來(lái)執(zhí)行原始任務(wù)。

使用 Java 動(dòng)態(tài)代理的先決條件

它是 Java 編程語(yǔ)言中一個(gè)相對(duì)高級(jí)的主題,因?yàn)樗枰恍V泛的 Java 知識(shí)。計(jì)劃使用 Java 動(dòng)態(tài)代理的開(kāi)發(fā)人員必須了解反射類(lèi)的使用或字節(jié)碼操作或如何編譯動(dòng)態(tài)生成的 Java 代碼。要?jiǎng)?chuàng)建字節(jié)碼,首先應(yīng)該學(xué)習(xí)如何使用 cglib 或 bytebuddy 或內(nèi)置的 Java 編譯器。

什么是調(diào)用處理程序?

InvocationHandler 是一個(gè)特殊的接口,它允許我們攔截對(duì)對(duì)象的任何方法調(diào)用并添加我們需要的附加行為。我們首先需要通過(guò)創(chuàng)建一個(gè)實(shí)現(xiàn)此接口的類(lèi)來(lái)創(chuàng)建我們的攔截器。它只包含一個(gè)方法:invoke(),其中原始對(duì)象作為參數(shù)傳遞,被代理。

當(dāng)我們考慮代理類(lèi)和它們調(diào)用的處理程序時(shí),就會(huì)明白為什么責(zé)任分離在這里非常重要。代理類(lèi)總是在運(yùn)行時(shí)生成,但代理類(lèi)調(diào)用的處理程序可以用源代碼編碼,并且可以在編譯時(shí)與整個(gè)程序的代碼一起編譯。

如何在代碼中使用 Java 動(dòng)態(tài)代理?

代理類(lèi)及其實(shí)例是使用 java.lang.reflect.Proxy 類(lèi)的靜態(tài)方法創(chuàng)建的。它是 JDK 的一部分,可以創(chuàng)建代理類(lèi)或直接創(chuàng)建它的實(shí)例。Java 內(nèi)置代理的使用相對(duì)容易一些。您需要做的就是實(shí)現(xiàn)一個(gè) java.lang.InvocationHandler,以便代理對(duì)象稍后可以調(diào)用它。在此之后,調(diào)用來(lái)自 Invocation Handler 的 invoke() 方法。

另一個(gè)方法,Proxy.getProxyClass 方法返回一個(gè)代理類(lèi)的 java.lang.Class 對(duì)象,給定一個(gè)類(lèi)加載器和一個(gè)接口數(shù)組。

根據(jù)動(dòng)態(tài)代理類(lèi) Java 文檔,必須傳遞給 Proxy.getProxyClass 的參數(shù)有一些限制:

interfaces 數(shù)組中的所有 Class 對(duì)象都必須表示接口,而不是類(lèi)或原始類(lèi)型。

interfaces 數(shù)組中的兩個(gè)元素不能引用相同的 Class 對(duì)象。

所有接口類(lèi)型必須通過(guò)指定的類(lèi)加載器按名稱(chēng)可見(jiàn)。

所有非公共接口必須在同一個(gè)包中;否則,代理類(lèi)將不可能實(shí)現(xiàn)所有接口,無(wú)論它定義在什么包中。

對(duì)于具有相同簽名的指定接口的任意數(shù)量的成員方法:

如果任何方法的返回類(lèi)型是 void 或原始類(lèi)型,則所有方法都必須具有相同的返回類(lèi)型。

如果不是,則其中一個(gè)方法必須具有可以分配給所有方法的所有返回類(lèi)型的返回類(lèi)型。

生成的代理類(lèi)不得超過(guò)虛擬機(jī)對(duì)類(lèi)施加的任何限制。

下面的代碼演示了在代碼中使用 Java 動(dòng)態(tài)代理的所有討論點(diǎn):

包代理;
導(dǎo)入java.lang.reflect.InvocationHandler;
導(dǎo)入java.lang.reflect.InvocationTargetException;
導(dǎo)入java.lang.reflect.Method;
導(dǎo)入java.lang.reflect.Proxy;
公共類(lèi) ProxyDemo {
接口如果{
void originalMethod(String str);
}
靜態(tài)類(lèi)原始實(shí)現(xiàn)If {
 public void originalMethod(String str) {
 System.out.println(str);
}
}
靜態(tài)類(lèi)Handler實(shí)現(xiàn)InvocationHandler {
 private final If original;
 public Handler(如果是原始的) {
 this.original = 原創(chuàng);
}
 public Object invoke(Object proxy, Method method, Object[] args)
 拋出 IllegalAccessException、IllegalArgumentException、
調(diào)用目標(biāo)異常{
 System.out.println("代理前:");
 method.invoke(原始, args);
 System.out.println("代理后:");
 返回空值;
}
}
 public static void main(String[] args){
 原始原始=新原始();
處理程序處理程序=新處理程序(原始);
 If a = (If) Proxy.newProxyInstance(If.class.getClassLoader(),
 新類(lèi)[] { If.class },
 處理程序);
a.originalMethod("你好");
}
}

現(xiàn)在,如果處理程序想要調(diào)用原始對(duì)象的原始方法,首先,它必須有權(quán)訪問(wèn)它。這不會(huì)由 Java 代理實(shí)現(xiàn)提供。開(kāi)發(fā)人員必須在代碼中手動(dòng)將此參數(shù)傳遞給處理程序?qū)嵗?/p>

代理對(duì)象

您一定已經(jīng)注意到,通常將一個(gè)名為“proxy”的對(duì)象作為參數(shù)傳遞給調(diào)用處理程序。這是由 Java 反射動(dòng)態(tài)生成的代理對(duì)象,而不是我們要代理的對(duì)象。因此,開(kāi)發(fā)人員為每個(gè)原始類(lèi)使用單獨(dú)的處理程序?qū)ο螅蛘咚麄円部梢允褂靡恍┕蚕韺?duì)象,如果有任何方法可以調(diào)用,他們也可以知道要調(diào)用哪個(gè)原始對(duì)象。您還可以創(chuàng)建一個(gè)調(diào)用處理程序和一個(gè)沒(méi)有任何原始對(duì)象的接口的代理。您不需要任何類(lèi)來(lái)實(shí)現(xiàn)代碼中的接口。動(dòng)態(tài)創(chuàng)建的代理類(lèi)會(huì)自動(dòng)實(shí)現(xiàn)接口。

Java 動(dòng)態(tài)代理實(shí)際應(yīng)用

Java 動(dòng)態(tài)代理在流行技術(shù)中被積極使用。在安全框架中可以看到一種常見(jiàn)的用法。

它用于在授權(quán)人員應(yīng)該使用的所有方法中添加安全檢查。使用 Java 動(dòng)態(tài)代理,可以添加安全檢查,導(dǎo)致用戶輸入有效憑據(jù),而無(wú)需復(fù)制驗(yàn)證碼來(lái)訪問(wèn)每個(gè)方法。

它還可以用于為方法創(chuàng)建日志。這也很容易通過(guò)使用代理類(lèi)來(lái)實(shí)現(xiàn)。您可以簡(jiǎn)單地向原始方法添加額外的代碼,以在最后顯示完整的日志。

以上就是關(guān)于“Java動(dòng)態(tài)代理的簡(jiǎn)介”,大家如果想了解更多相關(guān)知識(shí),不妨來(lái)關(guān)注一下動(dòng)力節(jié)點(diǎn)Java視頻教程,里面的課程內(nèi)容從入門(mén)到精通,細(xì)致全面,通俗易懂,很適合沒(méi)有基礎(chǔ)的小伙伴學(xué)習(xí),希望對(duì)大家能夠有所幫助。

提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)

免費(fèi)課程推薦 >>
技術(shù)文檔推薦 >>
主站蜘蛛池模板: 色狠狠综合网 | 日韩成人在线免费视频 | 欧美一级视频免费观看 | 亚洲第一天堂无码专区 | 亚洲无线码一区二区三区 | 亚洲综合欧美 | 免费老色鬼永久视频网站 | 亚洲国产日韩欧美在线as乱码 | 一级特黄aaa大片 | 在线看网站 | 看欧美一级片 | 老妇激情毛片 | 欧美专区一区二区三区 | 欧美一级特黄aa大片视频 | 福利免费观看 | 在线亚洲天堂 | 国产精品视频在这里有精品 | 亚洲丁香网 | 无码中文字幕日韩专区 | 一级毛片完整免费版 | 麻豆久久婷婷国产综合五月 | 亚洲国产精品乱码一区二区三区 | 国产伦一区二区三区免费 | 2048国产精品原创综合在线 | 久久精品一区 | 日本成人性视频 | 国产精品不卡视频 | 中文字幕亚洲综合久久菠萝蜜 | 无遮挡男女激烈免费动态图 | 亚洲一区二区三 | 日韩欧美国产中文 | 亚洲mv国产精品mv日本mv | 国产精品成人在线播放 | 深夜福利免费观看 | 色在线免费视频 | 高清国产亚洲va精品 | 免费一级大片儿 | 人人看人人爽 | 日产国产欧美韩国在线 | 色妇网 | zxfuil福利在线观看午夜 |