根據(jù)上篇《java靜態(tài)代理詳解》的介紹过蹂,你會(huì)發(fā)現(xiàn)每個(gè)代理類(lèi)只能為一個(gè)接口服務(wù)十绑,這樣程序開(kāi)發(fā)中必然會(huì)產(chǎn)生許多的代理類(lèi)
所以我們就會(huì)想辦法可以通過(guò)一個(gè)代理類(lèi)完成全部的代理功能,那么我們就需要用動(dòng)態(tài)代理
在上篇的示例中酷勺,一個(gè)代理只能代理一種類(lèi)型脆诉,而且是在編譯器就已經(jīng)確定被代理的對(duì)象甚亭。而動(dòng)態(tài)代理是在運(yùn)行時(shí)偶摔,通過(guò)反射機(jī)制實(shí)現(xiàn)動(dòng)態(tài)代理,并且能夠代理各種類(lèi)型的對(duì)象(動(dòng)態(tài)的)够挂;
具體實(shí)現(xiàn)類(lèi)
代理類(lèi)
客戶端代碼
可以看到梭姓,我們可以通過(guò)LogHandler代理不同類(lèi)型的對(duì)象,如果我們把對(duì)外的接口都通過(guò)動(dòng)態(tài)代理來(lái)實(shí)現(xiàn)嫩码,那么所有的函數(shù)調(diào)用最終都會(huì)經(jīng)過(guò)invoke函數(shù)的轉(zhuǎn)發(fā)铡恕,因此我們就可以在這里做一些自己想做的操作琢感,比如日志系統(tǒng)、事務(wù)探熔、攔截器驹针、權(quán)限控制等。這也就是AOP(面向切面編程)的基本原理诀艰。
動(dòng)態(tài)代理的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
動(dòng)態(tài)代理與靜態(tài)代理相比較柬甥,最大的好處是接口中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個(gè)集中的方法中處理(InvocationHandler.invoke)。這樣其垄,在接口方法數(shù)量比較多的時(shí)候苛蒲,我們可以進(jìn)行靈活處理,而不需要像靜態(tài)代理那樣每一個(gè)方法進(jìn)行中轉(zhuǎn)绿满。在本示例中看不出來(lái)臂外,因?yàn)閕nvoke方法體內(nèi)嵌入了具體的外圍業(yè)務(wù)(記錄任務(wù)處理前后時(shí)間并計(jì)算時(shí)間差),實(shí)際中可以類(lèi)似Spring AOP那樣配置外圍業(yè)務(wù)喇颁。
缺點(diǎn):
誠(chéng)然漏健,Proxy 已經(jīng)設(shè)計(jì)得非常優(yōu)美,但是還是有一點(diǎn)點(diǎn)小小的遺憾之處无牵,那就是它始終無(wú)法擺脫僅支持 interface 代理的桎梏漾肮,因?yàn)樗脑O(shè)計(jì)注定了這個(gè)遺憾厂抖【セ伲回想一下那些動(dòng)態(tài)生成的代理類(lèi)的繼承關(guān)系圖,它們已經(jīng)注定有一個(gè)共同的父類(lèi)叫 Proxy忱辅。Java 的繼承機(jī)制注定了這些動(dòng)態(tài)代理類(lèi)們無(wú)法實(shí)現(xiàn)對(duì) class 的動(dòng)態(tài)代理七蜘,原因是多繼承在 Java 中本質(zhì)上就行不通。