上一篇演示了,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方法呢?看来还要继续研究一下^_^