上一篇演示了,Spring得前通知、後通知、環繞通知,仔細想來前通知、後通知和異常通知,都應該是居於環繞通知開發的,想想如果都能控制目標函數是否能執行,那麼要在目標函數執行前後,或者目標函數執行過程中發生異常後進行一些處理,那不是太easy了嗎?,按照猜想,前通知、後通知,異常通知 應該是重寫invoke方法,在invoke方法裏面先執行before在執行proceed就是前通知,先執行proceed在執行afterReturning就是後通知,用在try 裏面執行invoke方法就是異常通知。我下面來看spring的源碼進行驗證
- /*
- *Copyright2002-2007theoriginalauthororauthors.
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packageorg.springframework.aop.framework.adapter;
- importjava.io.Serializable;
- importorg.aopalliance.intercept.MethodInterceptor;
- importorg.aopalliance.intercept.MethodInvocation;
- importorg.springframework.aop.MethodBeforeAdvice;
- importorg.springframework.util.Assert;
- /**
- *Interceptortowrapam{@linkorg.springframework.aop.MethodBeforeAdvice}.
- *UsedinternallybytheAOPframework;applicationdevelopersshouldnotneed
- *tousethisclassdirectly.
- *
- *@authorRodJohnson
- */
- publicclassMethodBeforeAdviceInterceptorimplementsMethodInterceptor,Serializable{
- privateMethodBeforeAdviceadvice;
- /**
- *CreateanewMethodBeforeAdviceInterceptorforthegivenadvice.
- *@paramadvicetheMethodBeforeAdvicetowrap
- */
- publicMethodBeforeAdviceInterceptor(MethodBeforeAdviceadvice){
- Assert.notNull(advice,"Advicemustnotbenull");
- this.advice=advice;
- }
- publicObjectinvoke(MethodInvocationmi)throwsThrowable{
- this.advice.before(mi.getMethod(),mi.getArguments(),mi.getThis());
- returnmi.proceed();
- }
- }
- /*
- *Copyright2002-2007theoriginalauthororauthors.
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packageorg.springframework.aop.framework.adapter;
- importjava.io.Serializable;
- importorg.aopalliance.intercept.MethodInterceptor;
- importorg.aopalliance.intercept.MethodInvocation;
- importorg.springframework.aop.AfterAdvice;
- importorg.springframework.aop.AfterReturningAdvice;
- importorg.springframework.util.Assert;
- /**
- *Interceptortowrapam{@linkorg.springframework.aop.AfterReturningAdvice}.
- *UsedinternallybytheAOPframework;applicationdevelopersshouldnotneed
- *tousethisclassdirectly.
- *
- *@authorRodJohnson
- */
- publicclassAfterReturningAdviceInterceptorimplementsMethodInterceptor,AfterAdvice,Serializable{
- privatefinalAfterReturningAdviceadvice;
- /**
- *CreateanewAfterReturningAdviceInterceptorforthegivenadvice.
- *@paramadvicetheAfterReturningAdvicetowrap
- */
- publicAfterReturningAdviceInterceptor(AfterReturningAdviceadvice){
- Assert.notNull(advice,"Advicemustnotbenull");
- this.advice=advice;
- }
- publicObjectinvoke(MethodInvocationmi)throwsThrowable{
- ObjectretVal=mi.proceed();
- this.advice.afterReturning(retVal,mi.getMethod(),mi.getArguments(),mi.getThis());
- returnretVal;
- }
- }
- /*
- *Copyright2002-2007theoriginalauthororauthors.
- *
- *LicensedundertheApacheLicense,Version2.0(the"License");
- *youmaynotusethisfileexceptincompliancewiththeLicense.
- *YoumayobtainacopyoftheLicenseat
- *
- *http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
- *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
- *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
- *SeetheLicenseforthespecificlanguagegoverningpermissionsand
- *limitationsundertheLicense.
- */
- packageorg.springframework.aop.framework.adapter;
- importjava.lang.reflect.InvocationTargetException;
- importjava.lang.reflect.Method;
- importjava.util.HashMap;
- importjava.util.Map;
- importorg.aopalliance.intercept.MethodInterceptor;
- importorg.aopalliance.intercept.MethodInvocation;
- importorg.apache.commons.logging.Log;
- importorg.apache.commons.logging.LogFactory;
- importorg.springframework.aop.AfterAdvice;
- importorg.springframework.util.Assert;
- /**
- *Interceptortowrapanafter-throwingadvice.
- *
- *<p>Thesignaturesonhandlermethodsonthe<code>ThrowsAdvice</code>
- *implementationmethodargumentmustbeoftheform:<br>
- *
- *<code>voidafterThrowing([Method,args,target],ThrowableSubclass);</code>
- *
- *<p>Onlythelastargumentisrequired.
- *
- *<p>Someexamplesofvalidmethodswouldbe:
- *
- *<preclass="code">publicvoidafterThrowing(Exceptionex)</pre>
- *<preclass="code">publicvoidafterThrowing(RemoteException)</pre>
- *<preclass="code">publicvoidafterThrowing(Methodmethod,Object[]args,Objecttarget,Exceptionex)</pre>
- *<preclass="code">publicvoidafterThrowing(Methodmethod,Object[]args,Objecttarget,ServletExceptionex)</pre>
- *
- *<p>ThisisaframeworkclassthatneednotbeuseddirectlybySpringusers.
- *
- *@authorRodJohnson
- *@authorJuergenHoeller
- */
- publicclassThrowsAdviceInterceptorimplementsMethodInterceptor,AfterAdvice{
- privatestaticfinalStringAFTER_THROWING="afterThrowing";
- privatestaticfinalLoglogger=LogFactory.getLog(ThrowsAdviceInterceptor.class);
- privatefinalObjectthrowsAdvice;
- /**Methodsonthrowsadvice,keyedbyexceptionclass*/
- privatefinalMapexceptionHandlerMap=newHashMap();
- /**
- *CreateanewThrowsAdviceInterceptorforthegivenThrowsAdvice.
- *@paramthrowsAdvicetheadviceobjectthatdefinestheexception
- *handlermethods(usuallya{@linkorg.springframework.aop.ThrowsAdvice}
- *implementation)
- */
- publicThrowsAdviceInterceptor(ObjectthrowsAdvice){
- Assert.notNull(throwsAdvice,"Advicemustnotbenull");
- this.throwsAdvice=throwsAdvice;
- Method[]methods=throwsAdvice.getClass().getMethods();
- for(inti=0;i<methods.length;i++){
- Methodmethod=methods[i];
- if(method.getName().equals(AFTER_THROWING)&
- //m.getReturnType()==null&&
- (method.getParameterTypes().length==1||method.getParameterTypes().length==4)&
- Throwable.class.isAssignableFrom(method.getParameterTypes()[method.getParameterTypes().length-1])
- ){
- //Haveanexceptionhandler
- this.exceptionHandlerMap.put(method.getParameterTypes()[method.getParameterTypes().length-1],method);
- if(logger.isDebugEnabled()){
- logger.debug("Foundexceptionhandlermethod:"+method);
- }
- }
- }
- if(this.exceptionHandlerMap.isEmpty()){
- thrownewIllegalArgumentException(
- "Atleastonehandlermethodmustbefoundinclass["+throwsAdvice.getClass()+"]");
- }
- }
- publicintgetHandlerMethodCount(){
- returnthis.exceptionHandlerMap.size();
- }
- /**
- *Determinetheexceptionhandlemethod.Canreturnnullifnotfound.
- *@paramexceptiontheexceptionthrown
- *@returnahandlerforthegivenexceptiontype
- */
- privateMethodgetExceptionHandler(Throwableexception){
- ClassexceptionClass=exception.getClass();
- if(logger.isTraceEnabled()){
- logger.trace("Tryingtofindhandlerforexceptionoftype["+exceptionClass.getName()+"]");
- }
- Methodhandler=(Method)this.exceptionHandlerMap.get(exceptionClass);
- while(handler==null&&!exceptionClass.equals(Throwable.class)){
- exceptionClass=exceptionClass.getSuperclass();
- handler=(Method)this.exceptionHandlerMap.get(exceptionClass);
- }
- if(handler!=null&&logger.isDebugEnabled()){
- logger.debug("Foundhandlerforexceptionoftype["+exceptionClass.getName()+"]:"+handler);
- }
- returnhandler;
- }
- publicObjectinvoke(MethodInvocationmi)throwsThrowable{
- try{
- returnmi.proceed();
- }
- catch(Throwableex){
- MethodhandlerMethod=getExceptionHandler(ex);
- if(handlerMethod!=null){
- invokeHandlerMethod(mi,ex,handlerMethod);
- }
- throwex;
- }
- }
- privatevoidinvokeHandlerMethod(MethodInvocationmi,Throwableex,Methodmethod)throwsThrowable{
- Object[]handlerArgs;
- if(method.getParameterTypes().length==1){
- handlerArgs=newObject[]{ex};
- }
- else{
- handlerArgs=newObject[]{mi.getMethod(),mi.getArguments(),mi.getThis(),ex};
- }
- try{
- method.invoke(this.throwsAdvice,handlerArgs);
- }
- catch(InvocationTargetExceptiontargetEx){
- throwtargetEx.getTargetException();
- }
- }
- }
通過spring的源碼可以確定剛剛的想法。現在明白了前通知和後通知,異常通知是怎麼實現的了,但是問題又來了,怎麼在我調用業務方法的前去執行invoke方法呢?看來還要繼續研究一下^_^