Spring學習筆記之前置通知、後置通知
在學習之前先提一個概念。
AsprctJ:Java社群裡最完整最流行的AOP框架。在Spring2.0以上版本中,可以使用基於AspectJ註解或基於XML配置的AOP。
啟用AspectJ註解支援
- 要在 Spring 中宣告 AspectJ 切面, 只需要在 IOC 容器中將切面宣告為 Bean 例項. 當在 Spring IOC 容器中初始化 AspectJ 切面之後, Spring IOC 容器就會為那些與 AspectJ 切面相匹配的 Bean 建立代理.
- 在 AspectJ 註解中, 切面只是一個帶有 @Aspect 註解的 Java 類.
- 通知是標註有某種註解的簡單的 Java 方法.
- AspectJ 支援 5 種類型的通知註解:
- @Before: 前置通知, 在方法執行之前執行
- @After: 後置通知, 在方法執行之後執行
- @AfterRunning: 返回通知, 在方法返回結果之後執行
- @AfterThrowing: 異常通知, 在方法丟擲異常之後
- @Around: 環繞通知, 圍繞著方法執行
SpringAOP
1).加入jar包
com.springsource.org.aopalliance-1.0.0.jar
com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar
spring-aop-4.3.11.RELEASE.jar
spring-aspects-4.3.11.RELEASE.jar
commons-logging-1.1.3.jar
spring-beans-4.3.11.RELEASE.jar
spring-context-4.3.11.RELEASE.jar
spring-core-4.3.11.RELEASE.jar
spring-expression-4.3.11.RELEASE.jar
2).在配置檔案中加入aop的名稱空間
3).基於註解的方式
①.在配置檔案中加
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
②.把橫切關注點的程式碼抽象到切面的類中
i.切面首先是一個IOC中的bean,即加入@Component註解
ii.切面還需要加入@Aspect註解
③.在類中宣告各種通知
i.宣告一個方法
ii.在方法前加入通知
- @Before: 前置通知, 在方法執行之前執行
- @After: 後置通知, 在方法執行之後執行
- @AfterRunning: 返回通知, 在方法返回結果之後執行
- @AfterThrowing: 異常通知, 在方法丟擲異常之後
- @Around: 環繞通知, 圍繞著方法執行
④.可以在通知方法中宣告一個型別為JoinPoint的引數,然後就能訪問連結細節,如方法名稱和引數值
@Component
@Aspect
public class LoggingAspect {
//宣告該方法是一個前置通知:在目標方法開始之前執行
@Before("execution(* com.jhh.spring.aop.impl.*.*(*, *))")
public void beforeMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " begins with " + args);
}
//後置通知:在目標方法執行後(無論是否發生異常)執行的通知
//在後置通知中還不能訪問目標方法執行的結果,執行結果在返回通知中訪問
@After("execution(* com.jhh.spring.aop.impl.*.*(*, *))")
public void afterMethod(JoinPoint joinPoint){
String methodName = joinPoint.getSignature().getName();
List<Object> args = Arrays.asList(joinPoint.getArgs());
System.out.println("The method " + methodName + " ends with " + args);
}
}
利用方法簽名編寫 AspectJ 切入點表示式
最典型的切入點表示式時根據方法的簽名來匹配各種方法:
- execution * com.atguigu.spring.ArithmeticCalculator.(..): 匹配 ArithmeticCalculator 中宣告的所有方法,第一個 代表任意修飾符及任意返回值. 第二個 * 代表任意方法. .. 匹配任意數量的引數. 若目標類與介面與該切面在同一個包中, 可以省略包名.
- execution public * ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 介面的所有公有方法.
- execution public double ArithmeticCalculator.*(..): 匹配 ArithmeticCalculator 中返回 double 型別數值的方法
- execution public double ArithmeticCalculator.*(double, ..): 匹配第一個引數為 double 型別的方法, .. 匹配任意數量任意型別的引數
- execution public double ArithmeticCalculator.*(double, double): 匹配引數型別為 double, double 型別的方法.