Spring AOP前置通知和后置通知


Spring AOP
  AspectJ:Java社區里最完整最流行的AOP框架
  在Spring2.0以上的版本中,可以使用基於AspectJ注解或基於XML配置的AOP


在Spring中啟用AspectJ注解支持
  要在Spring應用中使用AspectJ注解,必須在classpath下包含AspectJ類庫:aopalliance.jar、aspectj.weaver.jar和spring-aspects.jar
  將aop Schema添加到<beans>根元素中。
  要在Spring IOC容器中啟用AspectJ注解支持,只要早bean配置文件中定義一個空的XML元素<aop:aspectj-autoproxy>
  當Spring IOC容器偵測到bean配置文件中的<aop:aspectj-autoproxy>元素時,會自動為與AspectJ切面匹配的bean創建代理


用AspectJ注解聲明切面
  要在Spring中聲明AspectJ切面,只需要在IOC容器中將切面聲明為bean實例。當在Spring IOC容器中初始化AspectJ切面之后,Spring IOC容器就會為那些與AspectJ切面相匹配的bean創建代理
  在AspectJ注解中,切面只是一個帶有@AspectJ注解的Java類
  通知是標注有某種注解的簡單的Java方法
  AspectJ支持5種類型的通知注解:
    @Before:前置通知,在方法執行之前返回
    @After:后置通知,在方法執行后執行
    @AfterRunning:返回通知,在方法返回結果之后執行
    @AfterThrowing:異常通知,在方法拋出異常之后
    @Around:環繞通知,圍繞着方法執行

利用方法簽名編寫AspectJ切入點表達式
  最典型的切入點表達式時根據方法的簽名來匹配各種方法:
    -execution * com.yl.spring.aop.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類型的方法

后置通知
  后置通知是在連接點完成之后執行的,即連接點返回結果或者拋出異常的時候,下面的后置通知記錄了方法的終止。
  一個切面可以包括一個或者多個通知

LoggingAspect.java

 1 package com.yl.spring.aop.impl;
 2 
 3 import java.util.Arrays;
 4 import java.util.List;
 5 
 6 import org.aspectj.lang.JoinPoint;
 7 import org.aspectj.lang.annotation.After;
 8 import org.aspectj.lang.annotation.Aspect;
 9 import org.aspectj.lang.annotation.Before;
10 import org.springframework.stereotype.Component;
11 
12 //這個類聲明為一個切面:需要把該類放入到IOC容器中;再聲明為一個切面
13 @Aspect
14 @Component
15 public class LoggingAspect {
16     
17     //聲明該方法是一個前置通知:在目標方法開始之前執行
18     //@Before("execution(public int com.yl.spring.aop.impl.ArithmeticCalculatorImpl.add(int, int))")
19     @Before("execution(* com.yl.spring.aop.impl.*.*(..))")
20     public void beforeMethod(JoinPoint joinpoint) {
21         String methodName = joinpoint.getSignature().getName();
22         List<Object> args = Arrays.asList(joinpoint.getArgs());
23         System.out.println("The method " + methodName + " begins with " + args);
24     }
25     //后置通知:在目標方法執行后(無論是否發生異常),執行的通知
26     //在后置通知中,還不能訪問目標方法執行的結果
27     @After("execution(* com.yl.spring.aop.impl.*.*(..))")
28     public void afterMethod(JoinPoint joinPoint) {
29         String methodName = joinPoint.getSignature().getName();
30         List<Object> args = Arrays.asList(joinPoint.getArgs());
31         System.out.println("The method " + methodName + " end with " + args);
32     }
33     
34 }

配置文件applicationContext.xml:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4     xmlns:aop="http://www.springframework.org/schema/aop"
 5     xmlns:context="http://www.springframework.org/schema/context"
 6     xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
 7         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 8         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">
 9     
10     <!-- 配置自動掃描的包 -->
11     <context:component-scan base-package="com.yl.spring.aop.impl"></context:component-scan>
12     
13     <!-- 使AspectJ注解起作用:自動為匹配的類生成代理對象 -->
14     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
15     
16 </beans>

 

測試類:

 1 package com.yl.spring.aop.impl;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 public class Main {
 7     public static void main(String[] args) {
 8         
 9         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
10         
11         ArithmeticCalculator arithmeticCalculator = ctx.getBean(ArithmeticCalculator.class);
12         
13         int result = arithmeticCalculator.add(4, 6);
14         System.out.println("result: " + result);
15         
16         result = arithmeticCalculator.mul(4, 6);
17         System.out.println("result: " + result);
18     } 
19 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM