JDK动态代理实现简单AOP--转
JDK?動(dòng)態(tài)代理是?java?反射的一個(gè)重要特性。它在某種方面為?java?提供了動(dòng)態(tài)性的特性,給應(yīng)用帶來(lái)了無(wú)限的空間。大名鼎鼎的?Hessian?、?Spring AOP?基于動(dòng)態(tài)代理實(shí)現(xiàn)。本文將簡(jiǎn)單的介紹?JDK?動(dòng)態(tài)代理使用。
?
關(guān)于代理模式
?
代理模式是非常常用的一種設(shè)計(jì)模式,在我們的應(yīng)用中經(jīng)常被使用。一般場(chǎng)景是,我們有一個(gè)現(xiàn)成的類,它的功能比較的完善了,但是還是存在某些欠缺,這個(gè)時(shí)候我們需要去擴(kuò)展一些新的功能,但又不想去重造輪子,這個(gè)時(shí)候可以使用代理類來(lái)替代原來(lái)的目標(biāo)類,通過(guò)組合的模式,增加一種為目標(biāo)類增加一些額外的功能。
代理模式的類結(jié)構(gòu)圖一般如下:
?
圖1:代理模式類結(jié)構(gòu)圖
圖2:代理模式序列圖
?
JDK?動(dòng)態(tài)代理
?
所謂?JDK?動(dòng)態(tài)代理就是在運(yùn)行時(shí)動(dòng)態(tài)生成紅色的代理類的過(guò)程。和靜態(tài)代理不一樣的地方是靜態(tài)代理在編譯期就要完成代理類?的實(shí)現(xiàn)。那么動(dòng)態(tài)代理是如何實(shí)現(xiàn)的呢?
根據(jù)下面的例子,一步一步來(lái)看。
假設(shè)有這樣一個(gè)接口?Speak:
?
?
實(shí)現(xiàn)類?PeopleSpeak.
?
?
?
當(dāng)我們?nèi)フ{(diào)用?PersonSpeak?的?sayHello?的時(shí)候,很顯然是輸出?hello?。現(xiàn)在我們需要通過(guò)動(dòng)態(tài)代理在運(yùn)行時(shí)動(dòng)態(tài)的生成Speak?的代理類,并在調(diào)用?sayHello?方法的前后做一些輸出。完成類似?aop?的功能。
根據(jù)以上的思路,我們需要有一個(gè)?PersonSpeak?的代理類,它持了?PersonSpeak?的對(duì)象,這樣就能很方便的完成這個(gè)任務(wù)。如果用靜態(tài)代理實(shí)現(xiàn)顯然是很簡(jiǎn)單,那么用動(dòng)態(tài)代理如何實(shí)現(xiàn)呢?
這個(gè)時(shí)候我們可以使用?java?反射里的?Proxy?類。此類是?JDK?動(dòng)態(tài)代理的核心類。?Proxy?類擁有一個(gè)在運(yùn)行期動(dòng)態(tài)創(chuàng)建類的功能。動(dòng)態(tài)的去創(chuàng)建一個(gè)?Speak?的子類,同時(shí)該子類持有?PersonSpeak?類的一個(gè)實(shí)例,該子類的功能就是實(shí)現(xiàn)上述第一部分代理類的功能。
關(guān)于?java?反射的?Method?、?Field?、?Class?、?Construtor?等這里不做介紹,重點(diǎn)介紹?Proxy和?InvocationHandler?類。
Proxy和InvocationHandler?類簡(jiǎn)介
Proxy?類提供了非常重要的方法,該方法能夠動(dòng)態(tài)的生成幾個(gè)接口的實(shí)現(xiàn)類。具體的實(shí)現(xiàn)過(guò)程由?ProxyGenerator?類來(lái)實(shí)現(xiàn),這是比較低層的一個(gè)類,這里不做過(guò)多描述。同時(shí)該動(dòng)態(tài)類需要持有一個(gè)實(shí)現(xiàn)了?InvocationHandler?接口的子類對(duì)象。InvocationHandler?接口的子類對(duì)象是我們目標(biāo)類的又一層代理。對(duì)于接口里面的每個(gè)方法實(shí)現(xiàn),都是通過(guò)調(diào)用InvocationHandler?接口的子類對(duì)象的反射調(diào)用。也就是說(shuō)動(dòng)態(tài)代理類實(shí)際上是?InvocationHandler?子類對(duì)象的一個(gè)代理。那么?InvocationHandler?子類對(duì)象有時(shí)我們目標(biāo)類的代理。通過(guò)這樣層層代理我們就能實(shí)現(xiàn)上述的功能了。這句話可能不是很好理解,但是確實(shí)就是這么實(shí)現(xiàn)的,也許通過(guò)下面的圖就能更好的理解:
?
圖3:JDK動(dòng)態(tài)代理調(diào)用過(guò)程
?
可以從上圖看出來(lái),?JDK?動(dòng)態(tài)反射并不是那么簡(jiǎn)單的一層代理,而是通過(guò)層層代理,最終通過(guò)?Method?的反射來(lái)調(diào)用目標(biāo)對(duì)象的方法,而?aop?的實(shí)現(xiàn)可以放在?InvocationHandler?的是實(shí)現(xiàn)類里。
那么根據(jù)上述關(guān)于動(dòng)態(tài)代理的簡(jiǎn)介,要實(shí)現(xiàn)?PersonSpeak?的?aop?,需要做兩件事情
?
具體實(shí)現(xiàn)如下:
可以看出該類的?invoke?方法實(shí)現(xiàn)?aop?的關(guān)鍵,所有方法都是通過(guò)?invoke?來(lái)調(diào)用,?invoke?內(nèi)部通過(guò)反射來(lái)調(diào)用目標(biāo)對(duì)象?target?,同時(shí)在調(diào)用前后實(shí)現(xiàn)了?aop?。
?
?
?
ProxyFactory?主要是通過(guò)反射的?Proxy?類動(dòng)態(tài)的去創(chuàng)建接口的子類,同時(shí)該子類是?InvocationHandler?的一個(gè)代理,所有的方法實(shí)現(xiàn),都是通過(guò)?InvocationHandler?代理來(lái)調(diào)用。
?
最后來(lái)看下?Main?函數(shù):
?
?
?
?
得到的輸出結(jié)果如下:
??sayHello invoked!
hello
sayHello return!
?
?
從輸出結(jié)果可以看出紅色的輸出部分正是我們通過(guò)動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)的。通過(guò)如上的過(guò)程完成了正果動(dòng)態(tài)代理的過(guò)程。
除了實(shí)現(xiàn)?AOP?,動(dòng)態(tài)代理還可以用于實(shí)現(xiàn)遠(yuǎn)程服務(wù)代理。比如說(shuō)?Hessian?就是通過(guò)動(dòng)態(tài)創(chuàng)建遠(yuǎn)程服務(wù)代理類來(lái)調(diào)用遠(yuǎn)程服務(wù),從而使應(yīng)用對(duì)遠(yuǎn)程服務(wù)透明化。?Hessian?調(diào)用過(guò)程如下:
?
圖4:Hessian遠(yuǎn)程服務(wù)調(diào)用過(guò)程
?
總結(jié)
?
JDK?動(dòng)態(tài)代理是?java?反射的一個(gè)非常重要的特性,?JDK?動(dòng)態(tài)代理類還可以用來(lái)作為?SOAP?的遠(yuǎn)程服務(wù)代理類,總之它在某種程度上提供了?java?的動(dòng)態(tài)性的特點(diǎn),為應(yīng)用提供了很大的靈活性。
?
原文:http://blog.csdn.net/abing37/article/details/5449401
轉(zhuǎn)載于:https://www.cnblogs.com/davidwang456/p/3942082.html
總結(jié)
以上是生活随笔為你收集整理的JDK动态代理实现简单AOP--转的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 跨平台传输中使用base64来保证非as
- 下一篇: txt文件导入mysql--转