AOP最近被炒得非常的熱,各種各樣的AOP框架層出不窮。在AOP方面,我無(wú)意于去做一個(gè)完整的框架,支持各種AOP的特性,其實(shí)從實(shí)際我們項(xiàng)目經(jīng)歷上來(lái)分析??梢缘贸觯诮^大多數(shù)情況下,AOP的很多高級(jí)特性是用不上的,比如靜態(tài)代碼注入。為類(lèi)添加運(yùn)行時(shí)的構(gòu)造函數(shù),改變類(lèi)的繼承關(guān)系等等。其實(shí)我們最常用的還是攔截器,關(guān)于這個(gè)話題,可能是比較有爭(zhēng)議的,畢竟每個(gè)人的立場(chǎng)和觀點(diǎn)是不同的。針對(duì)我目前所涉及的應(yīng)用域來(lái)講,一個(gè)完整的攔截器框架已經(jīng)足夠了。
一個(gè)典型的攔截器框架至少應(yīng)該包括三個(gè)部分:
1、可聲明的攔截點(diǎn);
2、靈活的攔截器序列;
3、對(duì)攔截對(duì)象的代理封裝;
攔截點(diǎn)可以基于具體的應(yīng)用環(huán)境去靈活申明,這點(diǎn)可以參考Cocoon里的Pipeline。這里不用多說(shuō),大家看了后續(xù)的攔截點(diǎn)的定義代碼就一目了然了。關(guān)于攔截器的具體定義,也在隨后的部分提供,這里首先探討被攔截對(duì)象的代理的實(shí)現(xiàn)機(jī)制。
所謂代理,就是對(duì)被攔截對(duì)象的一個(gè)包裝,通過(guò)該包裝類(lèi),可以非常自然的對(duì)被包裝對(duì)象添加我們自定義的行為,比如調(diào)用攔截器進(jìn)行攔截操作。
我們來(lái)看AOP的代理接口的定義:
package
org.sunny.core.aop;
import
java.lang.reflect.InvocationHandler;
import
org.sunny.exception.SunnyException;
import
java.util.List;
/**
*
該類(lèi)是一個(gè)攔截器的處理中心,所有的業(yè)務(wù)邏輯的方法調(diào)用都會(huì)被該類(lèi)攔截。通過(guò)這種機(jī)制,
*
在這里就可以統(tǒng)一的實(shí)現(xiàn)如下的過(guò)濾器:
*
1、方法級(jí)鑒權(quán);
*
2、業(yè)務(wù)日志;
*
3、靜態(tài)屬性過(guò)濾。
*
等等功能。此外,你可以實(shí)現(xiàn)自己的攔截器,通過(guò)如下的接口:
*
< code>
*
< br>org.sunny.core.aop.interceptor.Interceptor
*
< /code>
*
并在全局配置文件里完成攔截器的配置。該攔截器就可以生效。
*
< p>Copyright:
Copyright
(c)
2005< /p>
*
< p>Company:
Sunny虛擬開(kāi)發(fā)組< /p>
*
@author
高雁冰
*
@version
1.0
*/
public
interface
AopProxy
{
????/** ????*設(shè)置該動(dòng)態(tài)代理需要代理的對(duì)象 ????*@paramdelegate具體被代理的對(duì)象(實(shí)例) ????*/ ????publicvoidsetDelegate(Objectdelegate); ???? ????/** ????*獲取通過(guò)該動(dòng)態(tài)代理處理后的業(yè)務(wù)代理對(duì)象 ????*@return該代理處理后的代理業(yè)務(wù)對(duì)象 ????*@throwsSunnyException ????*/ ????publicObjectgetProxy()throwsSunnyException; ???? ????/** ????*設(shè)置該代理類(lèi)需要處理的所有攔截器。 ????*@paraminterceptors攔截器集合 ????*/ ????publicvoidsetInterceptors(Listinterceptors); ???? } |
-----------------------------
Sunny目前提供了兩種代理的實(shí)現(xiàn)方式:
1、基于Java的動(dòng)態(tài)代理,原理大家可以到j(luò)ava.sun.com站點(diǎn)上去研究一番;
2、基于Cglib的字節(jié)碼映射的方式,這點(diǎn)大家也可以關(guān)注Cglig來(lái)找到具體的答案。
需要說(shuō)明的是,這兩種代理各自有不同的應(yīng)用域,某些情況是不能通用的?;贘ava的動(dòng)態(tài)代理要求被代理對(duì)象必須基于接口編程,即每個(gè)被代理對(duì)象有一個(gè)明確的接口。而基于Cglib的代理則不在此限制。
下面貼出源代碼:
----------------------------------------
package
org.sunny.core.aop;
//import
java.lang.reflect.*;
import
org.sunny.exception.SunnyException;
import
org.sunny.cfg.PltMessage;
import
org.sunny.core.aop.interceptor.InterceptorUtil;
import
java.lang.reflect.InvocationHandler;
import
java.lang.reflect.Method;
import
java.util.List;
/**
*
采用Java動(dòng)態(tài)代理的方式實(shí)現(xiàn)攔截器機(jī)制。
*
Copyright:
Copyright
(c)
2005
*
< p>Company:
Sunny虛擬開(kāi)發(fā)組< /p>
*
@author
高雁冰({@link
mailto:haiger@163.com})
*
@version
1.0
*/
public
class
DynamicProxy
implements
AopProxy,InvocationHandler
{
????privateObjectdelegate;//具體代理的業(yè)務(wù)邏輯對(duì)象 ????privateInterceptorUtilinterceptorUtil; ???? ????/** ????*默認(rèn)構(gòu)造函數(shù),由于該動(dòng)態(tài)代理的實(shí)現(xiàn)需要通過(guò)Class.newInstance來(lái)調(diào)用(被框架),所以需要 ????*提供該默認(rèn)構(gòu)造函數(shù),需要注意的是。在這之后,需要調(diào)用該類(lèi)的setDelegate方法來(lái)具體設(shè)置該 ????*類(lèi)具體代理哪個(gè)對(duì)象。 ????*/ ????publicDynamicProxy() ????{ ????????//... ????} ???? ???? ????/** ????*IOC機(jī)制,通過(guò)運(yùn)行時(shí)傳入需要代理的業(yè)務(wù)邏輯對(duì)象。 ????*@paramdelegate需要代理的業(yè)務(wù)邏輯對(duì)象 ????*/ ????publicDynamicProxy(Objectdelegate) ????{ ????????setDelegate(delegate); ????} ???? ????/** ????*設(shè)置該動(dòng)態(tài)代理需要代理的對(duì)象 ????*@paramdelegate具體被代理的對(duì)象(實(shí)例) ????*/ ????publicvoidsetDelegate(Objectdelegate) ????{ ????????this.delegate=delegate; ????} ???? ????/** ????*設(shè)置該代理類(lèi)需要處理的所有攔截器。 ????*@paraminterceptors攔截器集合 ????*/ ????publicvoidsetInterceptors(Listinterceptors) ????{ ????????interceptorUtil=newInterceptorUtil(interceptors); ????} ???? ????/** ????*獲取通過(guò)該動(dòng)態(tài)代理處理后的業(yè)務(wù)代理對(duì)象 ????*@return該代理處理后的代理業(yè)務(wù)對(duì)象 ????*@throwsSunnyException ????*/ ????publicObjectgetProxy()throwsSunnyException ????{ ????????if(null==delegate) ????????{ ????????????thrownewSunnyException(PltMessage.getInstance().getMessage( ????????????"BLA_IMPL_DELEGATE_NOT_SET")); ????????} ???????? ????????//構(gòu)造該業(yè)務(wù)邏輯的包裝類(lèi) ????????Objectproxy=java.lang.reflect.Proxy.newProxyInstance( ????????delegate.getClass().getClassLoader(), ????????delegate.getClass().getInterfaces() ????????,this); ???????? ????????returnproxy; ????} ???? ???? ????/** ????*攔截器的方法實(shí)現(xiàn),該方法調(diào)用代理的業(yè)務(wù)邏輯的方法。 ????*@paramproxy被代理的類(lèi) ????*@parammethod被調(diào)用的業(yè)務(wù)方法 ????*@paramargs調(diào)用業(yè)務(wù)方法的輸入?yún)?shù) ????*@returnObject業(yè)務(wù)方法調(diào)用的返回值 ????*@throwsThrowable業(yè)務(wù)方法拋出的異常,該異常目前在外圍系統(tǒng)去捕獲的時(shí)候需要一些 ????*技巧,你應(yīng)該這樣(用getCause()方法)來(lái)捕獲原始拋出的異常(范例代碼) ????*< code> ????*< br>try ????*< br>{ ????*< br>... ????*< br>}catch(Throwabletb) ????*< br>{ ????*< br>System.out.println(tb.getCause().getMessage()); *< br>} *< /code>歲 */ publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throws Throwable { ????//調(diào)用所有的攔截器,對(duì)方法行為進(jìn)行攔截操作 ????interceptorUtil.before(delegate,method,args); ???? ????//具體業(yè)務(wù)邏輯方法的調(diào)用 ????Objectresult=null; ????try ????{ ????????result=method.invoke(delegate,args); ????}catch(Throwablee) ????{ ????????//對(duì)日志進(jìn)行攔截操作 ????????interceptorUtil.exception(delegate,method,args,e); ????} ???? ????//業(yè)務(wù)邏輯調(diào)用完成,對(duì)結(jié)果進(jìn)行攔截操作 ????interceptorUtil.after(delegate,method,args,result); ???? ????returnresult; } }
|
---------------Cglib代理類(lèi)--------------------
packageorg.sunny.core.aop;
importjava.lang.reflect.Method; importnet.sf.cglib.proxy.MethodInterceptor; importnet.sf.cglib.proxy.Enhancer; importnet.sf.cglib.proxy.MethodProxy; importorg.sunny.exception.SunnyException; importorg.sunny.cfg.PltMessage; importorg.sunny.core.aop.interceptor.InterceptorUtil; importjava.util.List; /** *采用Cglib代理的方式實(shí)現(xiàn)攔截器機(jī)制。需要注意的是: *由于目前EJB的實(shí)現(xiàn)方式是采用靜態(tài)-動(dòng)態(tài)Stub的實(shí)現(xiàn)。Cgblib在這種對(duì)象的代理生成上有一 *些問(wèn)題,(EJB的Object的Stub是一個(gè)Finnal的類(lèi),不能完成代理),因此,如果系統(tǒng)采用EJB作為 *業(yè)務(wù)邏輯,則攔截器引擎只能使用: *< code> *org.sunny.blaccess.impl.DynanicProxyReactor *< /code> *Copyright:Copyright(c)2005 *< p>Company:Sunny虛擬開(kāi)發(fā)組< /p> *@author高雁冰({@linkmailto:haiger@163.com}) *@version1.5 */
publicclassCglibProxyimplementsMethodInterceptor,AopProxy { ????privateObjectdelegate;//被代理的業(yè)務(wù)對(duì)象 ????privateEnhancerenhancer=newEnhancer(); ????privateInterceptorUtilinterceptorUtil; ???? ????/** ????*設(shè)置該動(dòng)態(tài)代理需要代理的對(duì)象 ????*@paramdelegate具體被代理的對(duì)象(實(shí)例) ????*/ ????publicvoidsetDelegate(Objectdelegate) ????{ ????????this.delegate=delegate; ????} ???? ????/** ????*設(shè)置該代理類(lèi)需要處理的所有攔截器。 ????*@paraminterceptors攔截器集合 ????*/ ????publicvoidsetInterceptors(Listinterceptors) ????{ ????????interceptorUtil=newInterceptorUtil(interceptors); ????} ???? ????/** ????*獲取通過(guò)該動(dòng)態(tài)代理處理后的業(yè)務(wù)代理對(duì)象 ????*@return該代理處理后的代理業(yè)務(wù)對(duì)象 ????*@throwsSunnyException ????*/ ????publicObjectgetProxy()throwsSunnyException ????{ ????????if(null==delegate) ????????{ ????????????thrownewSunnyException(PltMessage.getInstance().getMessage( ????????????"BLA_IMPL_DELEGATE_NOT_SET")); ????????} ????????if(-1!=delegate.getClass().getName().indexOf("$$")) ????????{ ????????????enhancer.setSuperclass(delegate.getClass().getSuperclass()); ????????????}else ????????????{ ????????????????enhancer.setSuperclass(delegate.getClass()); ????????????} ????????????enhancer.setCallback(this); ????????????returnenhancer.create(); ????????} ???????? ????????/** ????????*實(shí)現(xiàn)對(duì)業(yè)務(wù)邏輯方法的具體攔截操作。在該操作里,可以在業(yè)務(wù)邏輯方法調(diào)用前后或者拋出異常的 ????????*時(shí)候添加自己的控制,這里則選擇執(zhí)行系統(tǒng)配置的攔截器。 ????????*@paramo被代理對(duì)象 ????????*@parammethod訪問(wèn)的具體方法 ????????*@paramargs方法輸入?yún)?shù) ????????*@paramproxy方法代理 ????????*@return方法執(zhí)行結(jié)果 ????????*@throwsjava.lang.Throwable ????????*/ ????????publicObjectintercept(Objecto,Methodmethod,Object[]args,MethodProxyproxy) ????????throwsThrowable ????????{ ????????????//調(diào)用所有的攔截器,對(duì)方法行為進(jìn)行攔截操作 ????????????interceptorUtil.before(delegate,method,args); ???????????? ????????????//具體業(yè)務(wù)邏輯方法的調(diào)用 ????????????Objectresult=null; ????????????try ????????????{ ????????????????result=proxy.invokeSuper(o,args); ????????????}catch(Throwablee) ????????????{ ????????????????//對(duì)日志進(jìn)行攔截操作 ????????????????interceptorUtil.exception(delegate,method,args,e); ????????????} ???????????? ????????????//業(yè)務(wù)邏輯調(diào)用完成,對(duì)結(jié)果進(jìn)行攔截操作 ????????????interceptorUtil.after(delegate,method,args,result); ???????????? ????????????returnresult; ????????} ????????
|
posted on 2007-02-02 20:35
???MengChuChen 閱讀(292)
評(píng)論(0) 編輯 收藏 所屬分類(lèi):
Spring