SpringBoot之@Aspect注解解读
作者:小白不很白
这篇文章主要介绍了SpringBoot之@Aspect注解解读,AOP是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,而@Aspect 就是把一个类定义为切面供容器读取,需要的朋友可以参考下
@Aspect注解
AOP:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。而@Aspect 就是把一个类定义为切面供容器读取。
- @before: 前置通知,在方法执行之前执行。
- @After:后置通知,在方法执行后执行。
- @AfterReturning: 返回通知,在方法返回结果之后执行。
- @AfterThrowing:异常通知,在方法抛出异常之后执行。
- @Around:环绕通知,围绕着方法执行。
1. 实现步骤
1.1 导入jar包
这两个选一个就可以了,推荐使用第一个,因为第一个项目中肯定会用到的。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
1.2 创建一个实体类
@Component @Aspect public class TestAspect { @Pointcut("execution( * com.atguigu.gulimall.product.controller.CouponController.*(..))") private void log(){ } @Before("log()") public void TestBefore(){ System.out.println("在调用方法的时候都会调用这个切面"); }
把这个类加入到容器中,然后再添加上注解就可以就可以看成是一个切面容器。
2. 语法
execution( * com.atguigu.gulimall.product.controller.CouponController.*(..)); // 第一个* 代表任意修饰符及任意返回值下的CouponController类下的所有方法。 // 第二个* 代表CouponController类下的所有方法。 // (..) 代表任意参数
// 匹配CouponController类下面的所有共有方法。 @Pointcut("execution( public * com.atguigu.gulimall.product.controller.CouponController.*(..))") // 第一个* 代表任意返回值 // 第二个* 当表任意方法 //(..) 代表任意参数
// 返回double 类型数值的方法 @Pointcut("execution( public Double com.atguigu.gulimall.product.controller.CouponController.*(..))")
// 匹配第一个参数为Double的方法。 @Pointcut("execution( public Double com.atguigu.gulimall.product.controller.CouponController.*(Double,..))")
// 匹配两个参数都为double 的方法。 @Pointcut("execution( public Double com.atguigu.gulimall.product.controller.CouponController.*(Double,Double))")
3. 简单实现
3.1 @Before
在方法执行前执行该方法,并且可以通过(JoinPoint类)获取请求参数和方法。
@Component @Aspect public class TestAspect { @Pointcut("execution( * com.atguigu.gulimall.product.controller.CouponController.*(..))") private void log(){ } @Before("log()") public void TestBefore(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); String name = joinPoint.getSignature().getName(); System.out.println(Arrays.asList(args).toString() +" "+ name); } }
@RestController @RequestMapping("product/coupon") public class CouponController { /** * 列表 */ @RequestMapping("/list") public R list(@RequestBody Map<String, Object> params){ return R.ok().put("page", "测试专用"); } }
3.2 @After
后置通知,在方法执行后执行。可以通过(JoinPoint类)获取请求参数和方法。
当方法抛出异常的时候也不会影响执行切点方法,也就是说不管如何都是会执行切面方法的。
@Component @Aspect public class TestAspect { @Pointcut("execution( * com.atguigu.gulimall.product.controller.CouponController.*(..))") private void log(){ } @After("log()") public void TestBefore(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); String name = joinPoint.getSignature().getName(); System.out.println(Arrays.asList(args).toString() +" "+ name); } }
3.3 @AfterReturning
当方法正常执行返回后才执行次方法,如果抛出异常就不会执行此方法。
/** * 列表 */ @RequestMapping("/list") public R list(@RequestBody Map<String, Object> params){ PageUtils<CouponEntity> page = couponService.queryPage(params); List<CouponEntity> list = page.getList(); String s = JSONObject.toJSONString(list); // 当这行抛出异常的时候就不会再执行切点方法了。 int i = 1/0; return R.ok().put("page", s); }
@Component @Aspect public class TestAspect { @Pointcut("execution( * com.atguigu.gulimall.product.controller.CouponController.*(..))") private void log(){ } @AfterReturning("log()") public void TestBefore(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); String name = joinPoint.getSignature().getName(); System.out.println(Arrays.asList(args).toString() +" "+ name); } }
3.4 @AfterThrowing(“log()”)
只有在抛出异常的时候才会调用切点方法。如果不抛出异常就不会调用切点方法。
@RequestMapping("/list") public R list(@RequestBody Map<String, Object> params){ PageUtils<CouponEntity> page = couponService.queryPage(params); List<CouponEntity> list = page.getList(); String s = JSONObject.toJSONString(list); int i = 1/0; return R.ok().put("page", s); }
@Component @Aspect public class TestAspect { @Pointcut("execution( * com.atguigu.gulimall.product.controller.CouponController.*(..))") private void log(){ } @AfterThrowing("log()") public void TestBefore(JoinPoint joinPoint){ Object[] args = joinPoint.getArgs(); String name = joinPoint.getSignature().getName(); System.out.println(Arrays.asList(args).toString() +" "+ name); } }
3.5 @Around
- 使用 ProceedingJoinPoint 获取参数信息
- 使用joinPoint.proceed()方法调用方法。
- 只有调用上面的方法才能够执行方法
@Component @Aspect public class TestAspect { @Pointcut("execution( * com.atguigu.gulimall.product.controller.CouponController.*(..))") private void log(){ } @Around("log()") public R TestBefore(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); Object o = args[0]; HashMap<String, String> stringStringHashMap = null; if (o instanceof Map){ stringStringHashMap = (HashMap<String, String>) o; } if(stringStringHashMap.get("name").equals("xiaobai")){ // 当满足参数中name值xiaobai的时候,才会调用下面的方法。 R proceed = (R) joinPoint.proceed(); return proceed; }else { return R.ok().put("name","小周"); } } }
/** * 列表 */ @RequestMapping("/list") public R list(@RequestBody Map<String, Object> params){ PageUtils<CouponEntity> page = couponService.queryPage(params); List<CouponEntity> list = page.getList(); String s = JSONObject.toJSONString(list); return R.ok().put("page", s); }
4. 结合自定义注解实现
package com.atguigu.gulimall.product.annoation; import java.lang.annotation.*; /** * @author liruiqing * 注解和@Aspect注解之间的联合使用 */ @Documented @Target({ElementType.METHOD}) // 在方法上加 @Retention(RetentionPolicy.RUNTIME) // 运行时 public @interface AnnotationTest { }
@RequestMapping("/list") @AnnotationTest public R list(@RequestBody Map<String, Object> params){ PageUtils<CouponEntity> page = couponService.queryPage(params); List<CouponEntity> list = page.getList(); String s = JSONObject.toJSONString(list); return R.ok().put("page", s); }
@Pointcut("@annotation(com.atguigu.gulimall.product.annoation.AnnotationTest)") private void annotation(){ } @After("annotation()") public void testAnnotation(){ System.out.println("执行注解注释的方法后执行此方法"); }
这样就可以实现切面了。
到此这篇关于SpringBoot之@Aspect注解解读的文章就介绍到这了,更多相关@Aspect注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!