AOP示例(續)

上一篇演示了,Spring得前通知、後通知、環繞通知,仔細想來前通知、後通知和異常通知,都應該是居於環繞通知開發的,想想如果都能控制目標函數是否能執行,那麼要在目標函數執行前後,或者目標函數執行過程中發生異常後進行一些處理,那不是太easy了嗎?,按照猜想,前通知、後通知,異常通知 應該是重寫invoke方法,在invoke方法裏面先執行before在執行proceed就是前通知,先執行proceed在執行afterReturning就是後通知,用在try 裏面執行invoke方法就是異常通知。我下面來看spring的源碼進行驗證

  1. /*
  2. *Copyright2002-2007theoriginalauthororauthors.
  3. *
  4. *LicensedundertheApacheLicense,Version2.0(the"License");
  5. *youmaynotusethisfileexceptincompliancewiththeLicense.
  6. *YoumayobtainacopyoftheLicenseat
  7. *
  8. *http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  11. *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  12. *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  13. *SeetheLicenseforthespecificlanguagegoverningpermissionsand
  14. *limitationsundertheLicense.
  15. */
  16. packageorg.springframework.aop.framework.adapter;
  17. importjava.io.Serializable;
  18. importorg.aopalliance.intercept.MethodInterceptor;
  19. importorg.aopalliance.intercept.MethodInvocation;
  20. importorg.springframework.aop.MethodBeforeAdvice;
  21. importorg.springframework.util.Assert;
  22. /**
  23. *Interceptortowrapam{@linkorg.springframework.aop.MethodBeforeAdvice}.
  24. *UsedinternallybytheAOPframework;applicationdevelopersshouldnotneed
  25. *tousethisclassdirectly.
  26. *
  27. *@authorRodJohnson
  28. */
  29. publicclassMethodBeforeAdviceInterceptorimplementsMethodInterceptor,Serializable{
  30. privateMethodBeforeAdviceadvice;
  31. /**
  32. *CreateanewMethodBeforeAdviceInterceptorforthegivenadvice.
  33. *@paramadvicetheMethodBeforeAdvicetowrap
  34. */
  35. publicMethodBeforeAdviceInterceptor(MethodBeforeAdviceadvice){
  36. Assert.notNull(advice,"Advicemustnotbenull");
  37. this.advice=advice;
  38. }
  39. publicObjectinvoke(MethodInvocationmi)throwsThrowable{
  40. this.advice.before(mi.getMethod(),mi.getArguments(),mi.getThis());
  41. returnmi.proceed();
  42. }
  43. }
  1. /*
  2. *Copyright2002-2007theoriginalauthororauthors.
  3. *
  4. *LicensedundertheApacheLicense,Version2.0(the"License");
  5. *youmaynotusethisfileexceptincompliancewiththeLicense.
  6. *YoumayobtainacopyoftheLicenseat
  7. *
  8. *http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  11. *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  12. *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  13. *SeetheLicenseforthespecificlanguagegoverningpermissionsand
  14. *limitationsundertheLicense.
  15. */
  16. packageorg.springframework.aop.framework.adapter;
  17. importjava.io.Serializable;
  18. importorg.aopalliance.intercept.MethodInterceptor;
  19. importorg.aopalliance.intercept.MethodInvocation;
  20. importorg.springframework.aop.AfterAdvice;
  21. importorg.springframework.aop.AfterReturningAdvice;
  22. importorg.springframework.util.Assert;
  23. /**
  24. *Interceptortowrapam{@linkorg.springframework.aop.AfterReturningAdvice}.
  25. *UsedinternallybytheAOPframework;applicationdevelopersshouldnotneed
  26. *tousethisclassdirectly.
  27. *
  28. *@authorRodJohnson
  29. */
  30. publicclassAfterReturningAdviceInterceptorimplementsMethodInterceptor,AfterAdvice,Serializable{
  31. privatefinalAfterReturningAdviceadvice;
  32. /**
  33. *CreateanewAfterReturningAdviceInterceptorforthegivenadvice.
  34. *@paramadvicetheAfterReturningAdvicetowrap
  35. */
  36. publicAfterReturningAdviceInterceptor(AfterReturningAdviceadvice){
  37. Assert.notNull(advice,"Advicemustnotbenull");
  38. this.advice=advice;
  39. }
  40. publicObjectinvoke(MethodInvocationmi)throwsThrowable{
  41. ObjectretVal=mi.proceed();
  42. this.advice.afterReturning(retVal,mi.getMethod(),mi.getArguments(),mi.getThis());
  43. returnretVal;
  44. }
  45. }
  1. /*
  2. *Copyright2002-2007theoriginalauthororauthors.
  3. *
  4. *LicensedundertheApacheLicense,Version2.0(the"License");
  5. *youmaynotusethisfileexceptincompliancewiththeLicense.
  6. *YoumayobtainacopyoftheLicenseat
  7. *
  8. *http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. *Unlessrequiredbyapplicablelaworagreedtoinwriting,software
  11. *distributedundertheLicenseisdistributedonan"ASIS"BASIS,
  12. *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied.
  13. *SeetheLicenseforthespecificlanguagegoverningpermissionsand
  14. *limitationsundertheLicense.
  15. */
  16. packageorg.springframework.aop.framework.adapter;
  17. importjava.lang.reflect.InvocationTargetException;
  18. importjava.lang.reflect.Method;
  19. importjava.util.HashMap;
  20. importjava.util.Map;
  21. importorg.aopalliance.intercept.MethodInterceptor;
  22. importorg.aopalliance.intercept.MethodInvocation;
  23. importorg.apache.commons.logging.Log;
  24. importorg.apache.commons.logging.LogFactory;
  25. importorg.springframework.aop.AfterAdvice;
  26. importorg.springframework.util.Assert;
  27. /**
  28. *Interceptortowrapanafter-throwingadvice.
  29. *
  30. *<p>Thesignaturesonhandlermethodsonthe<code>ThrowsAdvice</code>
  31. *implementationmethodargumentmustbeoftheform:<br>
  32. *
  33. *<code>voidafterThrowing([Method,args,target],ThrowableSubclass);</code>
  34. *
  35. *<p>Onlythelastargumentisrequired.
  36. *
  37. *<p>Someexamplesofvalidmethodswouldbe:
  38. *
  39. *<preclass="code">publicvoidafterThrowing(Exceptionex)</pre>
  40. *<preclass="code">publicvoidafterThrowing(RemoteException)</pre>
  41. *<preclass="code">publicvoidafterThrowing(Methodmethod,Object[]args,Objecttarget,Exceptionex)</pre>
  42. *<preclass="code">publicvoidafterThrowing(Methodmethod,Object[]args,Objecttarget,ServletExceptionex)</pre>
  43. *
  44. *<p>ThisisaframeworkclassthatneednotbeuseddirectlybySpringusers.
  45. *
  46. *@authorRodJohnson
  47. *@authorJuergenHoeller
  48. */
  49. publicclassThrowsAdviceInterceptorimplementsMethodInterceptor,AfterAdvice{
  50. privatestaticfinalStringAFTER_THROWING="afterThrowing";
  51. privatestaticfinalLoglogger=LogFactory.getLog(ThrowsAdviceInterceptor.class);
  52. privatefinalObjectthrowsAdvice;
  53. /**Methodsonthrowsadvice,keyedbyexceptionclass*/
  54. privatefinalMapexceptionHandlerMap=newHashMap();
  55. /**
  56. *CreateanewThrowsAdviceInterceptorforthegivenThrowsAdvice.
  57. *@paramthrowsAdvicetheadviceobjectthatdefinestheexception
  58. *handlermethods(usuallya{@linkorg.springframework.aop.ThrowsAdvice}
  59. *implementation)
  60. */
  61. publicThrowsAdviceInterceptor(ObjectthrowsAdvice){
  62. Assert.notNull(throwsAdvice,"Advicemustnotbenull");
  63. this.throwsAdvice=throwsAdvice;
  64. Method[]methods=throwsAdvice.getClass().getMethods();
  65. for(inti=0;i<methods.length;i++){
  66. Methodmethod=methods[i];
  67. if(method.getName().equals(AFTER_THROWING)&
  68. //m.getReturnType()==null&&
  69. (method.getParameterTypes().length==1||method.getParameterTypes().length==4)&
  70. Throwable.class.isAssignableFrom(method.getParameterTypes()[method.getParameterTypes().length-1])
  71. ){
  72. //Haveanexceptionhandler
  73. this.exceptionHandlerMap.put(method.getParameterTypes()[method.getParameterTypes().length-1],method);
  74. if(logger.isDebugEnabled()){
  75. logger.debug("Foundexceptionhandlermethod:"+method);
  76. }
  77. }
  78. }
  79. if(this.exceptionHandlerMap.isEmpty()){
  80. thrownewIllegalArgumentException(
  81. "Atleastonehandlermethodmustbefoundinclass["+throwsAdvice.getClass()+"]");
  82. }
  83. }
  84. publicintgetHandlerMethodCount(){
  85. returnthis.exceptionHandlerMap.size();
  86. }
  87. /**
  88. *Determinetheexceptionhandlemethod.Canreturnnullifnotfound.
  89. *@paramexceptiontheexceptionthrown
  90. *@returnahandlerforthegivenexceptiontype
  91. */
  92. privateMethodgetExceptionHandler(Throwableexception){
  93. ClassexceptionClass=exception.getClass();
  94. if(logger.isTraceEnabled()){
  95. logger.trace("Tryingtofindhandlerforexceptionoftype["+exceptionClass.getName()+"]");
  96. }
  97. Methodhandler=(Method)this.exceptionHandlerMap.get(exceptionClass);
  98. while(handler==null&&!exceptionClass.equals(Throwable.class)){
  99. exceptionClass=exceptionClass.getSuperclass();
  100. handler=(Method)this.exceptionHandlerMap.get(exceptionClass);
  101. }
  102. if(handler!=null&&logger.isDebugEnabled()){
  103. logger.debug("Foundhandlerforexceptionoftype["+exceptionClass.getName()+"]:"+handler);
  104. }
  105. returnhandler;
  106. }
  107. publicObjectinvoke(MethodInvocationmi)throwsThrowable{
  108. try{
  109. returnmi.proceed();
  110. }
  111. catch(Throwableex){
  112. MethodhandlerMethod=getExceptionHandler(ex);
  113. if(handlerMethod!=null){
  114. invokeHandlerMethod(mi,ex,handlerMethod);
  115. }
  116. throwex;
  117. }
  118. }
  119. privatevoidinvokeHandlerMethod(MethodInvocationmi,Throwableex,Methodmethod)throwsThrowable{
  120. Object[]handlerArgs;
  121. if(method.getParameterTypes().length==1){
  122. handlerArgs=newObject[]{ex};
  123. }
  124. else{
  125. handlerArgs=newObject[]{mi.getMethod(),mi.getArguments(),mi.getThis(),ex};
  126. }
  127. try{
  128. method.invoke(this.throwsAdvice,handlerArgs);
  129. }
  130. catch(InvocationTargetExceptiontargetEx){
  131. throwtargetEx.getTargetException();
  132. }
  133. }
  134. }

通過spring的源碼可以確定剛剛的想法。現在明白了前通知和後通知,異常通知是怎麼實現的了,但是問題又來了,怎麼在我調用業務方法的前去執行invoke方法呢?看來還要繼續研究一下^_^

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章