成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

你真的完全了解Java動(dòng)態(tài)代理嗎?看這篇就夠了

haitiancoder / 3610人閱讀

摘要:動(dòng)態(tài)地代理,可以猜測(cè)一下它的含義,在運(yùn)行時(shí)動(dòng)態(tài)地對(duì)某些東西代理,代理它做了其他事情。所以動(dòng)態(tài)代理的內(nèi)容重點(diǎn)就是這個(gè)。所以下一篇我們來(lái)細(xì)致了解下的到底是怎么使用動(dòng)態(tài)代理的。

之前講了《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》,本來(lái)打算下一篇講講Srping的AOP的,但是其中會(huì)涉及到Java的動(dòng)態(tài)代理,所以先多帶帶一篇來(lái)了解下Java的動(dòng)態(tài)代理到底是什么,Java是怎么實(shí)現(xiàn)它的。

動(dòng)態(tài)代理看起來(lái)好像是個(gè)什么高大上的名詞,但其實(shí)并沒(méi)有那么復(fù)雜,直接從字面就很容易理解。動(dòng)態(tài)地代理,可以猜測(cè)一下它的含義,在運(yùn)行時(shí)動(dòng)態(tài)地對(duì)某些東西代理,代理它做了其他事情。先不去搞清楚這個(gè)動(dòng)態(tài)代理真正的含義,我們來(lái)舉個(gè)生動(dòng)的例子來(lái)理解下它到底做了什么。

一個(gè)例子

一個(gè)程序員Developer,他會(huì)開(kāi)發(fā)code,他調(diào)試debug。

程序員有很多分類(lèi),其中有Java程序員JavaDeveloper,他會(huì)開(kāi)發(fā)Java代碼,會(huì)調(diào)試Java代碼。

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

Zack的這種“特異功能”是后天練出來(lái)的,并沒(méi)有哪種程序員有這種特性。雖然我們也可以定義一個(gè)擁有這樣特性的程序員,但是擁有各種亂七八糟特性的程序千千萬(wàn)。我們什么時(shí)候才能定義完,而能保證不漏呢?

其實(shí)我們沒(méi)有必要去定義他,因?yàn)樗呛筇祓B(yǎng)成的,我們應(yīng)該在這個(gè)程序員的成長(zhǎng)期去實(shí)現(xiàn)這個(gè)特性,而不是在他出生之前定義。

我們來(lái)看下代碼是怎么實(shí)現(xiàn)的

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

但是真正的Zack(代理后)
Zack is praying for the code!
Zack is coding java
Zack"s have no bug!No need to debug!

Proxy.newProxyInstance()

回看下上面是如何使用動(dòng)態(tài)代理的使用。生成一個(gè)實(shí)例對(duì)象,然后用Proxy的newInstance方法對(duì)這個(gè)實(shí)例對(duì)象代理生成一個(gè)代理對(duì)象。

這里有一個(gè)非常關(guān)鍵的人,也是比較少人去理解它的。為什么要傳zack的類(lèi)加載和zack的接口呢?
有沒(méi)有留意到zackProxy的類(lèi)型是Developer接口,而不是一個(gè)實(shí)現(xiàn)類(lèi)。因?yàn)閦ack在被代理后生成的對(duì)象,并不屬于Developer接口的任何一個(gè)實(shí)現(xiàn)類(lèi)。但是它是基于Developer接口和zack的類(lèi)加載代理出來(lái)的。

看下newProxyInstance()的接口定義

這三個(gè)參數(shù)具體的含義來(lái)看看注解是怎么描述的

loder,選用的類(lèi)加載器。因?yàn)榇淼氖莦ack,所以一般都會(huì)用加載zack的類(lèi)加載器。

interfaces,被代理的類(lèi)所實(shí)現(xiàn)的接口,這個(gè)接口可以是多個(gè)。

h,綁定代理類(lèi)的一個(gè)方法。

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

InvocationHandler


根據(jù)注解描述可知,InvocationHandler作用就是,當(dāng)代理對(duì)象的原本方法被調(diào)用的時(shí)候,會(huì)綁定執(zhí)行一個(gè)方法,這個(gè)方法就是InvocationHandler里面定義的內(nèi)容,同時(shí)會(huì)替代原本方法的結(jié)果返回。

InvocationHandler接收三個(gè)參數(shù)

proxy,代理后的實(shí)例對(duì)象。

method,對(duì)象被調(diào)用方法。

args,調(diào)用時(shí)的參數(shù)。

在上面的例子里,

如果最后的return語(yǔ)句改成

return method.invoke(proxy, agrs);

invoke的對(duì)象不是zack,而是proxy,根據(jù)上面的說(shuō)明猜猜會(huì)發(fā)生什么?
是的,會(huì)不停地循環(huán)調(diào)用。因?yàn)閜roxy是代理類(lèi)的對(duì)象,當(dāng)該對(duì)象方法被調(diào)用的時(shí)候,會(huì)觸發(fā)InvocationHandler,而InvocationHandler里面又調(diào)用一次proxy里面的對(duì)象,所以會(huì)不停地循環(huán)調(diào)用。并且,proxy對(duì)應(yīng)的方法是沒(méi)有實(shí)現(xiàn)的。所以是會(huì)循環(huán)的不停報(bào)錯(cuò)

動(dòng)態(tài)代理的原理

通過(guò)上面的講解,相信大家對(duì)動(dòng)態(tài)代理的使用理解得比較深刻了。那動(dòng)態(tài)代理到底是怎么實(shí)現(xiàn)的呢,我們來(lái)看看源碼其中關(guān)鍵的地方。
在newProxyInstance()發(fā)放中有這樣幾段。

其實(shí)大概就是把接口復(fù)制出來(lái),通過(guò)這些接口和類(lèi)加載器,拿到這個(gè)代理類(lèi)cl。然后通過(guò)反射的技術(shù)復(fù)制拿到代理類(lèi)的構(gòu)造函數(shù)(這部分代碼在Class類(lèi)中的getConstructor0方法),最后通過(guò)這個(gè)構(gòu)造函數(shù)new個(gè)一對(duì)象出來(lái),同時(shí)用InvocationHandler綁定這個(gè)對(duì)象。

動(dòng)態(tài)代理的使用場(chǎng)景

動(dòng)態(tài)代理的好處我們從例子就能看出來(lái),它比較靈活,可以在運(yùn)行的時(shí)候才切入改變類(lèi)的方法,而不需要預(yù)先定義它。

動(dòng)態(tài)代理一般我們比較少去手寫(xiě),但我們用得其實(shí)非常多。在Spring項(xiàng)目中用的注解,例如依賴(lài)注入的@Bean、@Autowired,事務(wù)注解@Transactional等都有用到,換言之就是Srping的AOP(切面編程)。

這種場(chǎng)景的使用是動(dòng)態(tài)代理最佳的落地點(diǎn),可以非常靈活地在某個(gè)類(lèi),某個(gè)方法,某個(gè)代碼點(diǎn)上切入我們想要的內(nèi)容,就是動(dòng)態(tài)代理其中的內(nèi)容。所以下一篇我們來(lái)細(xì)致了解下Spring的AOP到底是怎么使用動(dòng)態(tài)代理的。

如果覺(jué)得還不錯(cuò),請(qǐng)關(guān)注公眾號(hào):Zack說(shuō)碼

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/77106.html

相關(guān)文章

  • 從源碼入手,一文帶讀懂Spring AOP面向切面編程

    摘要:,,面向切面編程。,切點(diǎn),切面匹配連接點(diǎn)的點(diǎn),一般與切點(diǎn)表達(dá)式相關(guān),就是切面如何切點(diǎn)。例子中,注解就是切點(diǎn)表達(dá)式,匹配對(duì)應(yīng)的連接點(diǎn),通知,指在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作。,織入,將作用在的過(guò)程。因?yàn)樵创a都是英文寫(xiě)的。 之前《零基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)》詳細(xì)講了Spring容器的初始化和加載的原理,后面《你真的完全了解Java動(dòng)態(tài)代理嗎?看這篇就夠了》介紹了下...

    wawor4827 評(píng)論0 收藏0
  • java序列化,看這篇就夠了

    摘要:序列化機(jī)制使得對(duì)象可以脫離程序的運(yùn)行而獨(dú)立存在。普通序列化接口是一個(gè)標(biāo)記接口,不用實(shí)現(xiàn)任何方法。如果此對(duì)象已經(jīng)序列化過(guò),則直接輸出編號(hào)即可。圖示上述序列化過(guò)程。一、序列化的含義、意義及使用場(chǎng)景二、序列化實(shí)現(xiàn)的方式1、Serializable1.1 普通序列化1.2 成員是引用的序列化1.3 同一對(duì)象序列化多次的機(jī)制1.4 java序列化算法潛在的問(wèn)題1.5 可選的自定義序列化2、Extern...

    Hydrogen 評(píng)論0 收藏0
  • JS正則表達(dá)式入門(mén),看這篇就夠了

    摘要:如果遇到非常的復(fù)雜的匹配,正則表達(dá)式的優(yōu)勢(shì)就更加明顯了。關(guān)于正則表達(dá)式書(shū)寫(xiě)規(guī)則,可查看,上面說(shuō)的很清楚了,我就不貼出來(lái)了。替換與正則表達(dá)式匹配的子串,并返回替換后的字符串。結(jié)語(yǔ)正則表達(dá)式并不難,懂了其中的套路之后,一切都變得簡(jiǎn)單了。 前言 在正文開(kāi)始前,先說(shuō)說(shuō)正則表達(dá)式是什么,為什么要用正則表達(dá)式?正則表達(dá)式在我個(gè)人看來(lái)就是一個(gè)瀏覽器可以識(shí)別的規(guī)則,有了這個(gè)規(guī)則,瀏覽器就可以幫我們判斷...

    wenzi 評(píng)論0 收藏0
  • 線程池?面試?看這篇就夠了

    摘要:手動(dòng)創(chuàng)建執(zhí)行線程存在以上問(wèn)題,而線程池就是用來(lái)解決這些問(wèn)題的。線程池詳解上面我們已經(jīng)知道了線程池的作用,而對(duì)于這樣一個(gè)好用,重要的工具,當(dāng)然已經(jīng)為我們提供了實(shí)現(xiàn),這也是本篇文章的重點(diǎn)。,線程池一旦空閑超過(guò)時(shí)間,線程都將被回收。 showImg(https://segmentfault.com/img/remote/1460000018476903); 本文原創(chuàng)地址,我的博客:https...

    antz 評(píng)論0 收藏0
  • ES6入門(mén),看這篇就夠了

    摘要:從入門(mén)到放棄是什么,黑歷史,不講,自己百度去。類(lèi)你沒(méi)有看錯(cuò),這里面的就沒(méi)有問(wèn)題的。之前我們用過(guò),和有了,再也不用這兩個(gè)貨了。一個(gè)函數(shù),可以遍歷狀態(tài)感覺(jué)就是狀態(tài)機(jī),好吧不說(shuō)了再說(shuō)就懵逼了。 ES6從入門(mén)到放棄 1.ES6是什么,黑歷史,不講,自己百度去。 2.在瀏覽器中如何使用? 1.babel babeljs.io在線編譯 2.traceur-----Google出的編譯器,把E...

    lewinlee 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<