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

這篇文章主要介紹“Java動(dòng)態(tài)代理指的是什么”,在日常操作中,相信很多人在Java動(dòng)態(tài)代理指的是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”Java動(dòng)態(tài)代理指的是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到西和網(wǎng)站設(shè)計(jì)與西和網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類(lèi)型包括:做網(wǎng)站、網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、主機(jī)域名、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋西和地區(qū)。

一、靜態(tài)代理

描述動(dòng)態(tài)代理之前,先看一看靜態(tài)代理。

定義一個(gè)程序員的接口,只干兩件事情(程序員太忙,別的做不了) 

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

Java程序員長(zhǎng)這個(gè)樣,他會(huì)開(kāi)發(fā)Java代碼,會(huì)調(diào)試Java代碼

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

有個(gè)很牛逼的叫 Farmerbrag 的程序員,他在開(kāi)發(fā)之前,會(huì)祈禱一下,這樣他開(kāi)發(fā)的代碼就不會(huì)有bug。

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

我們這么來(lái)描述Farmerbrag(代理類(lèi))

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

如果Farmerbrag只是一個(gè)普通的Java程序員,那么他的開(kāi)發(fā)結(jié)果是

Farmerbrag is coding java.

Farmerbrag is debugging java.

真正的Farmerbrag(Farmerbrag代理類(lèi))是這樣的 

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

Farmerbrag is praying for the code!

Farmerbrag is coding java.

Farmerbrag's code is bug-free and does not require debugging

靜態(tài)代理優(yōu)點(diǎn)不說(shuō)了,說(shuō)一下缺點(diǎn)

1、增加了代碼維護(hù)復(fù)雜度。代理類(lèi)和實(shí)現(xiàn)類(lèi)具有相同的接口,代理類(lèi)通過(guò)實(shí)現(xiàn)類(lèi)執(zhí)行具體的方法。這樣就出現(xiàn)了大量的代碼重復(fù)。如果接口增加一個(gè)方法,除了所有實(shí)現(xiàn)類(lèi)需要實(shí)現(xiàn)這個(gè)方法外,所有代理類(lèi)也需要實(shí)現(xiàn)此方法。

2、代理對(duì)象只服務(wù)于一種類(lèi)型的對(duì)象。如果要服務(wù)多類(lèi)型的對(duì)象,要為每一種對(duì)象都進(jìn)行代理,靜態(tài)代理在程序規(guī)模稍大時(shí)就無(wú)法勝任。 

二、動(dòng)態(tài)代理的例子

接著靜態(tài)代理的例子,F(xiàn)armerbrag會(huì)祈禱這個(gè)功能是他特有的,其他程序員不會(huì)。我們可以定義一個(gè)擁有這項(xiàng)特技的程序員(第一部分靜態(tài)代理就是這么做的),但其他程序員可能具有別的特技,根本定義不完?。ㄓ袥](méi)有感覺(jué)到某些業(yè)務(wù)需求很想這個(gè)場(chǎng)景)

其實(shí)我們不需要去定義他,這個(gè)技能可以后天習(xí)得??纯丛趺醋?? 

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

這個(gè)動(dòng)態(tài)代理的程序員執(zhí)行結(jié)果如下

Farmerbrag is praying for the code!

Farmerbrag is coding java.

Farmerbrag's code is bug-free and does not require debugging

farmerbragProxy的類(lèi)型是Developer接口,不是一個(gè)實(shí)現(xiàn)類(lèi)。farmerbrag在被代理后生成的對(duì)象,并不屬于Developer接口的任何一個(gè)實(shí)現(xiàn)類(lèi),是基于Developer接口和farmerbrag的類(lèi)加載代理出來(lái)的。(mybatis定義的mapper接口怎么就能被調(diào)用執(zhí)行呢)

看一下newProxyInstance()接口的定義 

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

包括三個(gè)參數(shù)

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

loader和interfaces決定這個(gè)類(lèi)到底是個(gè)怎么樣的類(lèi)。而h是InvocationHandler,決定這個(gè)代理類(lèi)到底是多了什么功能。所以動(dòng)態(tài)代理的內(nèi)容重點(diǎn)就是這個(gè)InvocationHandler。

動(dòng)態(tài)代理的例子采用了lambda表達(dá)式,主要代碼是對(duì)InvocationHandler的實(shí)現(xiàn)。

三、代碼分析

從寫(xiě)代碼的角度,前面2節(jié)已經(jīng)足夠了,下邊對(duì)原理進(jìn)行分析。

看看源碼其中關(guān)鍵的地方。在newProxyInstance()方法中有這樣幾段 

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

1、克隆接口

2、查找或生成指定的代理類(lèi)

3、通過(guò)反射,拿到代理類(lèi)的構(gòu)造函數(shù)

4、通過(guò)構(gòu)造函數(shù)new一個(gè)對(duì)象,并關(guān)聯(lián)InvocationHandler

看到這里有些人可能會(huì)更蒙,InvocationHandler到底是做什么的?反射(reflect)又是怎么回事?代碼到底是怎么就被串改了呢?

四、原理剖析

1、class文件及其加載(反射)

編譯器編譯Java文件,產(chǎn)生.class 文件存放在磁盤(pán)中,文件內(nèi)容是只有JVM虛擬機(jī)能夠識(shí)別的機(jī)器碼。JVM虛擬機(jī)讀取字節(jié)碼文件,取出二進(jìn)制數(shù)據(jù),加載到內(nèi)存中,解析.class 文件內(nèi)的信息,生成對(duì)應(yīng) Class對(duì)象 

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

通過(guò)一段代碼演示手動(dòng)加載class文件字節(jié)碼到系統(tǒng)內(nèi),轉(zhuǎn)換成class對(duì)象,再實(shí)例化的過(guò)程

被加載的類(lèi)我們復(fù)用前面的JavaDeveloper.class

自定義一個(gè)類(lèi)加載器 

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

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

執(zhí)行代碼得到如下結(jié)果

net.fengyu.proxy.JavaDeveloper

Farmerbrag is coding java.

以上代碼演示了,通過(guò)字節(jié)碼加載成class對(duì)象的過(guò)程

2、運(yùn)行期生成二進(jìn)制字節(jié)碼

JVM通過(guò)字節(jié)碼的二進(jìn)制信息加載類(lèi),如果我們?cè)谶\(yùn)行期的系統(tǒng)中,遵循Java編譯系統(tǒng)組織.class文件的格式和結(jié)構(gòu),生成相應(yīng)的二進(jìn)制數(shù)據(jù),然后把這個(gè)二進(jìn)制數(shù)據(jù)加載轉(zhuǎn)換成對(duì)應(yīng)的類(lèi),這樣,就完成了在代碼中,動(dòng)態(tài)創(chuàng)建一個(gè)類(lèi)的能力。第二節(jié)動(dòng)態(tài)代理例子顯然是這個(gè)能力的一個(gè)子集。 

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

有一些開(kāi)源框架支持運(yùn)行期生成二進(jìn)制字節(jié)碼這個(gè)功能,如ASM,Javassist

ASM 是一個(gè) Java 字節(jié)碼操控框架。能夠以二進(jìn)制形式修改已有類(lèi)或者動(dòng)態(tài)生成類(lèi)。ASM可以直接產(chǎn)生二進(jìn)制 class 文件,也可以在類(lèi)被加載入Java虛擬機(jī)之前動(dòng)態(tài)改變類(lèi)行為。Spring使用的CGLIB也采用ASM框架作為其字節(jié)碼操作的工具。

下邊一段代碼生成一個(gè)跟前面JavaDeveloper幾乎一樣的類(lèi)ASMDeveloper,使用上一小節(jié)的LoadClass類(lèi)運(yùn)行有相同的輸出

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

這個(gè)例子說(shuō)明,在代碼里生成字節(jié)碼,并動(dòng)態(tài)地加載成class對(duì)象,創(chuàng)建實(shí)例是完全可以實(shí)現(xiàn)的。動(dòng)態(tài)修改某個(gè)類(lèi)當(dāng)然也能做到(動(dòng)態(tài)代理就做這事)。

至此,原理層面基本已經(jīng)說(shuō)清楚了。

3、為什么是InvocationHandler

我們已經(jīng)具有能力動(dòng)態(tài)修改一個(gè)類(lèi)的代碼,使用ASM哪怕生成一個(gè)非常簡(jiǎn)單的類(lèi),代碼量也是又多又復(fù)雜。仔細(xì)思考代理模式中的代理Proxy角色。Proxy角色在執(zhí)行代理業(yè)務(wù)的時(shí)候,無(wú)非是在調(diào)用真正業(yè)務(wù)之前或者之后做一些“額外”業(yè)務(wù)。 

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

代理類(lèi)處理的邏輯很簡(jiǎn)單,在調(diào)用某個(gè)方法前及方法后做一些額外的業(yè)務(wù)。換一種思路就是,在觸發(fā)(invoke)真實(shí)角色的方法之前或者之后做一些額外的業(yè)務(wù)。為了構(gòu)造出具有通用、簡(jiǎn)單的代理類(lèi),可以將所有的觸發(fā)真實(shí)角色動(dòng)作交給一個(gè)觸發(fā)的管理器。這種管理器就是InvocationHandler。 

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

在這種模式之中,代理Proxy和RealSubject需要實(shí)現(xiàn)相同的功能(函數(shù)方法)。

面向?qū)ο蟮木幊讨?,想要約定Proxy和RealSubject實(shí)現(xiàn)相同的功能(函數(shù)方法)有兩種方式

a、定義一個(gè)功能接口,Proxy 和RealSubject都實(shí)現(xiàn)這個(gè)接口。

b、通過(guò)繼承,Proxy繼承自RealSubject,這樣Proxy則擁有了RealSubject的功能,

JDK中提供的創(chuàng)建動(dòng)態(tài)代理的機(jī)制采用a思路;而cglib采用b思路(spring兩者都使用了)。 

到此,關(guān)于“Java動(dòng)態(tài)代理指的是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

標(biāo)題名稱:Java動(dòng)態(tài)代理指的是什么
文章起源:http://bm7419.com/article12/pcoggc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、面包屑導(dǎo)航、小程序開(kāi)發(fā)、移動(dòng)網(wǎng)站建設(shè)、網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)公司

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)