動(dòng)態(tài)代理作為代理模式的一種擴(kuò)展形式,廣泛應(yīng)用于框架(尤其是基于AOP的框架)的設(shè)計(jì)與開(kāi)發(fā),本文將通過(guò)實(shí)例來(lái)講解Java動(dòng)態(tài)代理的實(shí)現(xiàn)過(guò)程。
成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),甘孜州企業(yè)網(wǎng)站建設(shè),甘孜州品牌網(wǎng)站建設(shè),網(wǎng)站定制,甘孜州網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷,網(wǎng)絡(luò)優(yōu)化,甘孜州網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。通常情況下,代理模式中的每一個(gè)代理類在編譯之后都會(huì)生成一個(gè)class文件,代理類所實(shí)現(xiàn)的接口和所代理的方法都被固定,這種代理被稱之為靜態(tài)代理(Static Proxy)。那么有沒(méi)有一種機(jī)制能夠讓系統(tǒng)在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建代理類?答案就是本文將要介紹的動(dòng)態(tài)代理(Dynamic Proxy)。動(dòng)態(tài)代理是一種較為高級(jí)的代理模式,它在事務(wù)管理、AOP(Aspect-OrientedProgramming,面向方面編程)等領(lǐng)域都發(fā)揮了重要的作用。
在傳統(tǒng)的代理模式中,客戶端通過(guò)Proxy類調(diào)用RealSubject類的request()方法,同時(shí)還可以在代理類中封裝其他方法(如preRequest()和postRequest()等)。如果按照這種方法使用代理模式,那么代理類和真實(shí)主題類都應(yīng)該是事先已經(jīng)存在的,代理類的接口和所代理方法都已明確指定,如果需要為不同的真實(shí)主題類提供代理類或者代理一個(gè)真實(shí)主題類中的不同方法,都需要增加新的代理類,這將導(dǎo)致系統(tǒng)中的類個(gè)數(shù)急劇增加,因此需要想辦法減少系統(tǒng)中類的個(gè)數(shù)。動(dòng)態(tài)代理可以讓系統(tǒng)能夠根據(jù)實(shí)際需要來(lái)動(dòng)態(tài)創(chuàng)建代理類,讓同一個(gè)代理類能夠代理多個(gè)不同的真實(shí)主題類而且可以代理不同的方法。
從JDK 1.3開(kāi)始,Java語(yǔ)言提供了對(duì)動(dòng)態(tài)代理的支持,Java語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)代理時(shí)需要用到位于java.lang.reflect包中的一些類,現(xiàn)簡(jiǎn)要說(shuō)明如下:
(1) Proxy類
Proxy類提供了用于創(chuàng)建動(dòng)態(tài)代理類和實(shí)例對(duì)象的方法,它是所創(chuàng)建的動(dòng)態(tài)代理類的父類,它最常用的方法如下:
(2) InvocationHandler接口
InvocationHandler接口是代理處理程序類的實(shí)現(xiàn)接口,該接口作為代理實(shí)例的調(diào)用處理者的公共父類,每一個(gè)代理類的實(shí)例都可以提供一個(gè)相關(guān)的具體調(diào)用處理者(InvocationHandler接口的子類)。在該接口中聲明了如下方法:
public Object invoke(Objectproxy, Method method, Object[] args):該方法用于處理對(duì)代理類實(shí)例的方法調(diào)用并返回相應(yīng)的結(jié)果,當(dāng)一個(gè)代理實(shí)例中的業(yè)務(wù)方法被調(diào)用時(shí)將自動(dòng)調(diào)用該方法。invoke()方法包含三個(gè)參數(shù),其中第一個(gè)參數(shù)proxy表示代理類的實(shí)例,第二個(gè)參數(shù)method表示需要代理的方法,第三個(gè)參數(shù)args表示代理方法的參數(shù)數(shù)組。
動(dòng)態(tài)代理類需要在運(yùn)行時(shí)指定所代理真實(shí)主題類的接口,客戶端在調(diào)用動(dòng)態(tài)代理對(duì)象的方法時(shí),調(diào)用請(qǐng)求會(huì)將請(qǐng)求自動(dòng)轉(zhuǎn)發(fā)給InvocationHandler對(duì)象的invoke()方法,由invoke()方法來(lái)實(shí)現(xiàn)對(duì)請(qǐng)求的統(tǒng)一處理。
下面通過(guò)一個(gè)簡(jiǎn)單實(shí)例來(lái)學(xué)習(xí)如何使用動(dòng)態(tài)代理模式:
Sunny軟件公司欲為公司OA系統(tǒng)數(shù)據(jù)訪問(wèn)層DAO增加方法調(diào)用日志,記錄每一個(gè)方法被調(diào)用的時(shí)間和調(diào)用結(jié)果,現(xiàn)使用動(dòng)態(tài)代理進(jìn)行設(shè)計(jì)和實(shí)現(xiàn)。
本實(shí)例完整代碼如下所示:
import java.lang.reflect.Proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Calendar; import java.util.GregorianCalendar; //抽象UserDAO:抽象主題角色 interface AbstractUserDAO { public Boolean findUserById(String userId); } //抽象DocumentDAO:抽象主題角色 interface AbstractDocumentDAO { public Boolean deleteDocumentById(String documentId); } //具體UserDAO類:真實(shí)主題角色 class UserDAO implements AbstractUserDAO { public Boolean findUserById(String userId) { if (userId.equalsIgnoreCase("張無(wú)忌")) { System.out.println("查詢ID為" + userId + "的用戶信息成功!"); return true; } else { System.out.println("查詢ID為" + userId + "的用戶信息失??!"); return false; } } } //具體DocumentDAO類:真實(shí)主題角色 class DocumentDAO implements AbstractDocumentDAO { public Boolean deleteDocumentById(String documentId) { if (documentId.equalsIgnoreCase("D001")) { System.out.println("刪除ID為" + documentId + "的文檔信息成功!"); return true; } else { System.out.println("刪除ID為" + documentId + "的文檔信息失?。?); return false; } } } //自定義請(qǐng)求處理程序類 class DAOLogHandler implements InvocationHandler { private Calendar calendar; private Object object; public DAOLogHandler() { } //自定義有參構(gòu)造函數(shù),用于注入一個(gè)需要提供代理的真實(shí)主題對(duì)象 public DAOLogHandler(Object object) { this.object = object; } //實(shí)現(xiàn)invoke()方法,調(diào)用在真實(shí)主題類中定義的方法 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeInvoke(); Object result = method.invoke(object, args); //轉(zhuǎn)發(fā)調(diào)用 afterInvoke(); return null; } //記錄方法調(diào)用時(shí)間 public void beforeInvoke(){ calendar = new GregorianCalendar(); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); int second = calendar.get(Calendar.SECOND); String time = hour + ":" + minute + ":" + second; System.out.println("調(diào)用時(shí)間:" + time); } public void afterInvoke(){ System.out.println("方法調(diào)用結(jié)束!" ); } }
當(dāng)前文章:Java動(dòng)態(tài)代理實(shí)現(xiàn)_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理-創(chuàng)新互聯(lián)
網(wǎng)站鏈接:http://www.rwnh.cn/article4/cephie.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、手機(jī)網(wǎng)站建設(shè)、面包屑導(dǎo)航、做網(wǎng)站、服務(wù)器托管、靜態(tài)網(wǎng)站
聲明:本網(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)
猜你還喜歡下面的內(nèi)容