Spring AOP中@Aspect 面向切面注解使用详解

匿名 (未验证) 提交于 2019-12-02 21:45:52

引言:

相关注解介绍如下:

@Aspect:作用是把当前类标识为一个切面供容器读取   @Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是 public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为 此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。 @Around:环绕增强,相当于MethodInterceptor @AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行 @Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有 @AfterThrowing:异常抛出增强,相当于ThrowsAdvice

二:Spring的配置文件 applicationContext.xml 中引入context、aop对应的命名空间;配置自动扫描的包,同时使切面类中相关方法中的注解生效,需自动地为匹配到的方法所在的类生成代理对象。

3、创建简单计算器的接口ArithmeticCalculator.java及实现类ArithmeticCalculatorImpl.java

package com.svse.aop;  public interface ArithmeticCalculator {      //定义四个简单的借口 加减乘除算法     int add(int i, int j);      int sub(int i, int j);      int mul(int i, int j);      int div(int i, int j); }
package com.svse.aop; import org.springframework.stereotype.Component;  //将实现类加入Spring的IOC容器进行管理 @Component("arithmeticCalculator") public class ArithmeticCalculatorImpl implements ArithmeticCalculator {      @Override     public int add(int i, int j) {          int result = i + j;             return result;     }      @Override     public int sub(int i, int j) {           int result = i - j;             return result;     }      @Override     public int mul(int i, int j) {           int result = i * j;             return result;     }      @Override     public int div(int i, int j) {           int result = i / j;             return result;     }  }

4、现在想在实现类中的每个方法执行前、后、以及是否发生异常等信息打印出来,需要把日志信息抽取出来,写到对应的切面的类中 LoggingAspect.java 中
要想把一个类变成切面类,需要两步,
① 在类上使用 @Component 注解 把切面类加入到IOC容器中
② 在类上使用 @Aspect 注解 使之成为切面类

package com.svse.aop;  import java.util.Arrays;  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.springframework.stereotype.Component;  import com.tencentcloudapi.vod.v20180717.VodClient;  /**  * 日志切面  *   * @author zhaoshuiqing<br>  * @date 2019年6月14日 下午3:03:29  */ @Component @Aspect public class LoggingAspect {      //现在想在实现类中的每个方法执行前、后、以及是否发生异常等信息打印出来,需要把日志信息抽取出来,写到对应的切面的类中 LoggingAspect.java 中      //要想把一个类变成切面类,需要两步,      //① 在类上使用 @Component 注解 把切面类加入到IOC容器中      //② 在类上使用 @Aspect 注解 使之成为切面类               /**      * 前置通知:目标方法执行之前执行以下方法体的内容       * @param jp      */     @Before("execution(* com.svse.aop.*.*(..))")     public void beforeMethod(JoinPoint jp){          String methodName =jp.getSignature().getName();          System.out.println("【前置通知】the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs()));     }           /**      * 返回通知:目标方法正常执行完毕时执行以下代码      * @param jp      * @param result      */     @AfterReturning(value="execution(* com.svse.aop.*.*(..))",returning="result")     public void afterReturningMethod(JoinPoint jp, Object result){          String methodName =jp.getSignature().getName();          System.out.println("【返回通知】the method 【" + methodName + "】 ends with 【" + result + "】");     }            /**      * 后置通知:目标方法执行之后执行以下方法体的内容,不管是否发生异常。      * @param jp      */     @After("execution(* com.svse.aop.*.*(..))")     public void afterMethod(JoinPoint jp){         System.out.println("【后置通知】this is a afterMethod advice...");     }                /**      * 异常通知:目标方法发生异常的时候执行以下代码      */     @AfterThrowing(value="execution(* com.qcc.beans.aop.*.*(..))",throwing="e")     public void afterThorwingMethod(JoinPoint jp, NullPointerException e){          String methodName = jp.getSignature().getName();          System.out.println("【异常通知】the method 【" + methodName + "】 occurs exception: " + e);     }             /**   * 环绕通知:目标方法执行前后分别执行一些代码,发生异常的时候执行另外一些代码   * @return    */  /*@Around(value="execution(* com.svse.aop.*.*(..))")  public Object aroundMethod(ProceedingJoinPoint jp){      String methodName = jp.getSignature().getName();      Object result = null;      try {          System.out.println("【环绕通知中的--->前置通知】:the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs()));          //执行目标方法          result = jp.proceed();          System.out.println("【环绕通知中的--->返回通知】:the method 【" + methodName + "】 ends with " + result);      } catch (Throwable e) {          System.out.println("【环绕通知中的--->异常通知】:the method 【" + methodName + "】 occurs exception " + e);      }            System.out.println("【环绕通知中的--->后置通知】:-----------------end.----------------------");      return result;  }*/  }

package com.svse.aop; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;  public class MainTest {      public static void main(String[] args) {                  //ClassPathXmlApplicationContext默认是加载src目录下的xml文件         ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");          ArithmeticCalculator arithmeticCalculator =(ArithmeticCalculator) ctx.getBean("arithmeticCalculator");                  System.out.println(arithmeticCalculator.getClass());         int result = arithmeticCalculator.add(3, 5);         System.out.println("result: " + result);                  result = arithmeticCalculator.div(5, 0);         System.out.println("result: " + result);     }  }

运行结果:

把其它代码都注释掉,把环绕通知的方法释放出来,测试结果如下:

至此AOP注解面向切面记录日志就写完了!
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!