Spring學習筆記四(AOP中的通知引數和註解開發)
1.前言
上一篇部落格介紹瞭如何通過AOP來切入我們想實現的公共性的功能,這篇部落格來講一下,當我們攔截到方法後,如何來獲取通知引數。這也是AOP的精髓所在,通過AOP可以實現偷樑換柱的功能。我們把原來要執行的方法的引數獲取到,然後換一套引數執行。下面來跟著我看一下吧!
2.AOP的通知引數
有時我們想通過AOP攔截到我們要加入通知的切點類的引數,通俗的說就像拿到攔截的方法的引數值,然後如果不合適的話,我們可以修改一下或者做一些其他的操作。例如使用者登入的功能,我們可以把驗證身份的功能抽離出來,然後在AOP中攔截到登陸方法中的引數,通過判斷使用者名稱來決定做下一步的操作。那麼如何來取出使用者名稱呢。
如果需要在通知方法中獲取原始方法的呼叫引數,需要在通知方法的第一個形參位置宣告JoinPoint型別的引數,使用該引數呼叫getArgs()方法可以獲得原始方法的呼叫引數列表Object[]
<span style="font-size:18px;">package com.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; //通知類 public class MyAdvice { public void before(JoinPoint jp,String a,int b){ //Object[] objs = jp.getArgs(); //System.out.println("before......"+objs[0]+","+objs[1]); System.out.println("before......"+a+","+b); } public void after(JoinPoint jp){ System.out.println("after......"); } public void afterReturning(JoinPoint jp,Object abc){ System.out.println("afterReturning......"+abc); } public void afterThrowing(JoinPoint jp){ System.out.println("afterThrowing......"); } //具有公共性的功能 public Object fn(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("aaaaaaa"); //獲取到執行的引數 Object[] obj= pjp.getArgs(); for (Object lb:obj) { System.out.println(lb); } //進行偷樑換柱的功能 Object ob= pjp.proceed(new Object[]{new Integer(6),new Integer(9)}); System.out.println("bbbbbbbbbbbbbbb"); return ob; } } </span>
注意:所有通知都可以通過JoinPoint獲得通知的引數,但是隻有around類別才可以執行替代攔截方法。
3.AOP通知返回值
2.afterReturning:在配置中設定returning屬性,值是變數名的值,與方法的形參進行對應1.只有afterReturning 與 around可以獲取方法的返回值
3.around:直接通過程式中的原始方法呼叫獲取,該方法返回值即為原始方法的返回值<aop:after-returning method="afterReturning"returning="abc"/>
publicvoid afterReturning(JoinPoint jp,Object abc){
System.out.println("afterReturning......"+abc);
}
4.AOP的註解開發publicObject around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("aroundbefore......");
//呼叫原始方法
Objectobj = pjp.proceed();
System.out.println("around after......"+obj);
return obj; 說明:對原始方法攔截後,最終的執行返回值取決於這裡
}
註解開發也特別的簡單,下面給出一個例項,與平常的XML配置類似
<span style="font-size:18px;">package cn.itcast.aop.annotation; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; //定義切面類 @Aspect public class BookAdvice { //切面 @Pointcut("execution(* cn.itcast.aop.annotation.BookService.add(..))") private void pt(){} //切點的順序 @Before("BookAdvice.pt()") public void before(JoinPoint jp){ System.out.println("before running......"); } @After("BookAdvice.pt()") public void after(){ System.out.println("after running......"); } @AfterReturning(value="BookAdvice.pt()",returning="abc") public void afterReturning(Object abc){ System.out.println("afterReturning running......"+abc); } @AfterThrowing(value="execution(* cn.itcast.aop.annotation.BookService.add(..))",throwing="t") public void afterThrowing(Throwable t){ System.out.println(t); System.out.println("afterThrowing running......"); } @Around("execution(* cn.itcast.aop.annotation.BookService.add(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("around before running......"); Object retValue = pjp.proceed(); System.out.println("around after running......"); return retValue; } } </span>
注意:上述的配置與XML一一對應起來的話,就會簡單很多。