AOP切面通知

需要用的基本的jar包:

aopalliance-1.0.jar
aspectj-1.6.8.jar
aspectjweaver-1.6.8.jar
commons-logging-1.1.3.jar
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar

1:基于注解的日志通知和验证通知:

定义接口:

1 package com.yinfu.spring.aop.impl;
2 
3 public interface ArithmeticCalculator {
4 
5     public int add(int i,int j);
6     public int sub(int i,int j);
7     public int mul(int i,int j);
8     public int div(int i,int j);
9 }

定义实现类:

 1 package com.yinfu.spring.aop.impl;
 2 
 3 import org.springframework.stereotype.Component;
 4 
 5 @Component("arithmeticCalculator")
 6 public class ArithmeticCalculatorImpl implements ArithmeticCalculator {
 7 
 8     @Override
 9     public int add(int i, int j) {
10         
11         int result = i+j;
12         return result;
13     }
14 
15     @Override
16     public int sub(int i, int j) {
17         int result = i-j;
18         return result;
19     }
20 
21     @Override
22     public int mul(int i, int j) {
23         int result = i*j;
24         return result;
25     }
26 
27     @Override
28     public int div(int i, int j) {
29         int result = i/j;
30         return result;
31     }
32 
33 }

定义spring的配置文件: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.0.xsd
 7         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 8         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 9 
10 <!--     <bean id="helloWorld" class="com.yinfu.spring.beans.HelloWorld">
11         <property name="name" value="fuck"></property>
12     </bean> -->
13     <!-- 配置自动扫描包 -->
14     <context:component-scan base-package="com.yinfu.spring.aop.impl"></context:component-scan>
15     
16     <!-- 使AspectJ注解起作用:自动为匹配的类生成代理对象 -->
17     <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
18     
19 </beans>

定义切面类:

  1 package com.yinfu.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.ProceedingJoinPoint;
  8 import org.aspectj.lang.annotation.After;
  9 import org.aspectj.lang.annotation.AfterReturning;
 10 import org.aspectj.lang.annotation.AfterThrowing;
 11 import org.aspectj.lang.annotation.Around;
 12 import org.aspectj.lang.annotation.Aspect;
 13 import org.aspectj.lang.annotation.Before;
 14 import org.aspectj.lang.annotation.Pointcut;
 15 import org.springframework.core.annotation.Order;
 16 import org.springframework.stereotype.Component;
 17 
 18 /**
 19  * 把此类声明为一个切面
 20  * 首相把该类放到IOC容器中,然后在声明为切面
 21  * @Aspect声明此类是一个切面
 22  * @Order声明切面的优先级,值越小优先级越高
 23  * @author lusong
 24  *
 25  */
 26 @Order(1)
 27 @Aspect
 28 @Component 
 29 public class LoggingAspect {
 30     
 31     
 32     //定义一个方法用于声明切入点表达式,因为表达式都相同,可以进行封装不过方法内不需要添加其他代码
 33     //使用@Pointcut声明切入点表达式
 34     /**
 35      * 此时下面的通知注解都可以将value值写成此方法名 如:@Before("declareJoinPointException()")即可
 36      */
 37     @Pointcut("execution(public int com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl.*(int, int))")
 38     public void declareJoinPointException(){}
 39 
 40     //1.前置通知:声明该方法是一个前置方法,在指定目标方法之前执行
 41     /**
 42      * before中写的是aspectj的表达式
 43      * public int可以用*代替,代表:任意修饰符和任意返回值
 44      * com.yinfu.spring.aop.impl代表包名
 45      * ArithmeticCalculatorImpl代表类名,可以用*代替,代表该包下的任意类
 46      * add代表方法名,可以用*好代替,代表该类下的任意方法
 47      * (int,int)参数类型,可以用..代替
 48      * @param joinPoint 链接点利用此链接点可以得到代理对象中的方法名称和参数等细节
 49      */
 50     @Before("execution(public int com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl.*(int, int))")
 51     public void beforeMethod(JoinPoint joinPoint ){
 52         String methodName = joinPoint.getSignature().getName();
 53         List<Object> args = Arrays.asList(joinPoint.getArgs());
 54         System.out.println("this method "+methodName+" begin"+args);
 55     }
 56     //2.后置通知:在目标方法执行后(无论是否发生异常),执行的通知
 57     //后置通知中还不能访问目标方法执行的结果
 58     @After("execution(public int com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl.*(int, int))")
 59     public void afterMethod(JoinPoint joinPoint ){
 60         String methodName = joinPoint.getSignature().getName();
 61         System.out.println("this method "+methodName+" end");
 62     }
 63     
 64     //3返回通知:在目标方法正常执行后,执行的通知
 65     //返回通知是可以访问到方法的返回值的
 66     @AfterReturning(value="execution(public int com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl.*(int, int))",returning="result")
 67     public void afterReturning(JoinPoint joinPoint ,Object result){
 68         String methodName = joinPoint.getSignature().getName();
 69         System.out.println("this method "+methodName+" end with "+result);
 70     }
 71     
 72     //4.异常通知:在目标方法出现异常时会执行代码
 73     //可以访问异常对象,指定异常类型,当出现指定的异常时才会执行代码
 74     //也就是Exception可以换成NullPoinException异常,当出现空指针异常的时候才会执行异常通知,其他异常不执行
 75     @AfterThrowing(value="execution(public int com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl.*(int, int))",throwing="ex")
 76     public void afterThrowing(JoinPoint joinPoint ,Exception ex){
 77         String methodName = joinPoint.getSignature().getName();
 78         System.out.println("this method "+methodName+" throw with "+ex);
 79     }
 80     
 81     //5.环绕通知
 82     //环绕通知携带ProceedingJoinPoint类型的参数
 83     //环绕通知类似于动态代理的全过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法
 84     //环绕通知必须有返回值,返回值即为目标方法的返回值
 85     @Around("execution(public int com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl.*(int, int))")
 86     public Object aroundMethod(ProceedingJoinPoint pjp){
 87         Object result = null;
 88         String methodName = pjp.getSignature().getName();
 89         Object[] args = pjp.getArgs();
 90         //执行目标方法
 91         try {
 92             //前置通知
 93             System.out.println("this aroundMethod "+methodName+" begin with "+Arrays.asList(args));
 94             result = pjp.proceed();
 95             //返回通知
 96             System.out.println("this aroundMethod "+methodName+" resutn with "+result);
 97         } catch (Throwable e) {
 98             //异常通知
 99             System.out.println("this aroundMethod "+methodName+" throw with "+e);
100         }
101         //后置通知
102         System.out.println("this aroundMethod "+methodName+" end ");
103         return result;
104     }
105     
106     
107 }

2.基于配置文件的日志通知和验证通知:

将类中的注解全部去掉,其他不变

此时的配置文件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.0.xsd
 7         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
 8         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
 9 
10     <!-- 配置方法对象bean -->
11     <bean id="arithmeticCalculator" class="com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl"></bean>
12     <!-- 配置切面bean -->
13     <bean id="loggingAspect" class="com.yinfu.spring.aop.impl.LoggingAspect"></bean>
14     <!-- 配置AOP切面 -->
15     <aop:config>
16         <!-- 配置切点表达式 -->
17         <aop:pointcut expression="execution(public int com.yinfu.spring.aop.impl.ArithmeticCalculatorImpl.*(int, int))" id="pointcut"/>
18         <!-- 配置切点及通知 -->
19         <aop:aspect ref="loggingAspect" order="1">
20             <aop:before method="beforeMethod" pointcut-ref="pointcut"/>
21             <aop:after method="afterMethod" pointcut-ref="pointcut"/>
22             <!-- 这里的returning值必须与切面类中定义的值是一样的 -->
23             <aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
24             <!-- 这里的throwing值必须与切面类中定义的值是一样的 -->
25             <aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="ex"/>
26             <aop:around method="aroundMethod" pointcut-ref="pointcut"/>
27         </aop:aspect>
28     </aop:config>
29     
30 </beans>
原文地址:https://www.cnblogs.com/lubolin/p/7656081.html