1、首先添加pom引用
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
2、aop五种通知类型示例代码
package com.example.demo.web; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //表示切入点 @Aspect @Component public class TestAop { //定义一个方法, 用于声明切入点表达式. 一般地, 该方法中再不需要添入其他的代码。 //使用 @Pointcut 来声明切入点表达式。 //后面的其他通知直接使用方法名来引用当前的切入点表达式。 //(..)表示任意参数 @Pointcut("execution(public * com.example.demo.web..*.*(..))") public void testAop() { } //前置通知:在方法执行前通知 @Before("testAop()") public void beforeMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); Object[] args = joinPoint.getArgs(); System.out.println(String.format("beforeMethod方法名称:%s,方法入参:%s", methodName, joinPoint.getArgs())); } //方法执行后通知: 在目标方法执行后无论是否发生异常,执行通知,不能访问目标方法的执行的结果。 @After("testAop()") public void afterMethod(JoinPoint joinPoint) { String methodName = joinPoint.getSignature().getName(); System.out.println(String.format("afterMethod方法名称:%s", methodName)); } //后置通知:在方法正常执行完成进行通知,可以访问到方法的返回值的。 @AfterReturning(value = "testAop()", returning = "result") public void afterReturning(JoinPoint joinPoint, Object result) { String methodName = joinPoint.getSignature().getName(); System.out.println(String.format("afterReturning方法名称:%s,方法出参:%s", methodName, result)); } //异常通知:在方法出现异常时进行通知,可以访问到异常对象,且可以指定在出现特定异常时在执行通知。 @AfterThrowing(value = "testAop()", throwing = "e") public void afterThrowing(JoinPoint joinPoint, Exception e) { String methodName = joinPoint.getSignature().getName(); System.out.println(String.format("afterThrowing方法名称:%s,异常参数:%s", methodName, e)); } //环绕通知:可以将要执行的方法(point.proceed())进行包裹执行,可以在前后添加需要执行的操作 @Around("testAop()") public Object around(ProceedingJoinPoint point) throws Throwable { System.out.println("环绕通知开始,方法入参:" + point.getArgs()); Object result = point.proceed(); System.out.println("环绕通知结束,方法返回参数:" + result); return result; } }
3、测试代码
@RestController public class HomeController { @RequestMapping("/index") public String index() throws Exception { System.out.println("控制器内部方法执行"); TimeUnit.SECONDS.sleep(1); //int a = 1 / 0; return "返回页面"; } }
注意区分@After和@AfterReturning区别,After不论方法是否执正常结束都会通知,而AfterReturning出现异常未正常结束则不会通知。
对接口请求进行简单的封装例子
@Aspect @Component @Slf4j public class WebLogAspect { @Pointcut("execution(public * com.example.demo.web..*.*(..))") public void webLog() { } //aop环绕通知拦截来搞一下 @Around("webLog()") public Object around(ProceedingJoinPoint point) throws Throwable { //获取请求的类名 String className = point.getTarget().getClass().getName(); //从切面织入点处通过反射机制获取织入点处的方法 MethodSignature signature = (MethodSignature) point.getSignature(); //获取请求的方法名 String methodName = signature.getMethod().getName(); log.info(String.format("类名:%s,方法名:%s,入参:%s", className, methodName, JsonHelper.ConvertToJson(point.getArgs()))); StopWatch watch = new StopWatch(); watch.start(); //执行方法 Object result = point.proceed(); watch.stop(); log.info(String.format("类名:%s,方法名:%s,耗时:%s,出参:%s", className, methodName, watch.getLastTaskTimeMillis(), JsonHelper.ConvertToJson(result))); return result; } }
参考链接:
https://www.jianshu.com/p/8649b0fe660f