1. 添加依赖

<!--        AOP依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2. 创建切面类

1. 创建切面类

      创建一个切面类,并使用 @Aspect 注解标记,并在这个类中定义切点和通知。

@Aspect // 表示这是一个切面
@Component // 托管到spring容器中
public class AccessRecordAspect {
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
    // 定义切点 匹配TestController中的test*方法
    @Pointcut("execution(* com.huan.web.controllers.TestController.test*(..))")
    public void a(){}

    // 使用后置增强,在方法正确执行后执行
    @AfterReturning("a()")
    public void record(JoinPoint joinPoint){
        System.out.println("记录访问记录");
        // 获取目标方法参数
        Object[] args = joinPoint.getArgs();
        System.out.println(args[0]);
    }
}

2. 切点表达式

      切点表达式通用模式:execution(修饰符模式? 返回类型模式 包名.类名.方法名(参数模式) 异常模式?)
      其中的 ? 表示该部分是可选的

  • 修饰符模式:可选部分,用于匹配方法的修饰符(如 public、private 等)。例如:public。
  • 返回类型模式:用于匹配方法的返回类型。可以使用通配符 * 表示任意返回类型。例如:*。
  • 包名:用于匹配方法所在的包名。例如:com.example.service。
  • 类名:用于匹配方法所在的类名。可以使用通配符 * 表示任意类。例如:*。
  • 方法名:用于匹配方法名。可以使用通配符 * 表示任意方法。例如:*。
  • 参数模式:用于匹配方法的参数类型。可以使用通配符 … 表示任意数量和类型的参数。例如:(…)。
  • 异常模式:可选部分,用于匹配方法抛出的异常类型。例如:throws IOException。

一些常见的切点表达式示例:

execution:
    用于匹配方法执行。
    语法:execution(修饰符模式? 返回类型模式 包名.类名.方法名(参数模式) 异常模式?)
    示例:execution(* com.example.service.*.*(..)) 匹配 com.example.service 包中的所有类的所有方法。

within:
    用于匹配指定类型内的方法。
    语法:within(type-pattern)
    示例:within(com.example.service..*) 匹配 com.example.service 包及其子包中的所有类。

this:
    用于匹配当前 AOP 代理对象的类型。
    语法:this(type)
    示例:this(com.example.service.UserService) 匹配代理对象是 UserService 类型的所有方法。

target:
    用于匹配目标对象的类型。
    语法:target(type)
    示例:target(com.example.service.UserService) 匹配目标对象是 UserService 类型的所有方法。

args:
    用于匹配方法参数的类型。
    语法:args(argument-type-pattern)
    示例:args(java.lang.String) 匹配所有参数为 String 类型的方法。

@annotation:
    用于匹配方法上具有指定注解的方法。
    语法:@annotation(annotation-type)
    示例:@annotation(org.springframework.transaction.annotation.Transactional) 匹配所有带有 @Transactional 注解的方法。

@within:
    用于匹配具有指定注解的类型内的方法。
    语法:@within(annotation-type)
    示例:@within(org.springframework.stereotype.Service) 匹配所有带有 @Service 注解的类中的方法。

@target:
    用于匹配目标对象类型上具有指定注解的方法。
    语法:@target(annotation-type)
    示例:@target(org.springframework.stereotype.Service) 匹配目标对象类型上带有 @Service 注解的方法。

@args:
    用于匹配运行时传递的参数具有指定注解的方法。
    语法:@args(annotation-type)
    示例:@args(org.springframework.web.bind.annotation.RequestBody) 匹配参数带有 @RequestBody 注解的方法。

3. 增强方法

  • @Before:在目标方法执行前执行。
  • @After:在目标方法执行后执行。
  • @AfterReturning:在目标方法正常返回后执行。
  • @AfterThrowing:在目标方法抛出异常后执行。
  • @Around:环绕增强,可以在目标方法执行前后执行。

      我之前简单测试了下五种增强方法的执行顺序(文章),结论如下:

  • 无异常时  执行顺序为:环绕增强(前)-> 前置增强 -> 目标方法 -> 返回增强 -> 后置增强 -> 环绕增强(后)
  • 有异常时  执行顺序为:环绕增强(前)-> 前置增强 -> 目标方法 -> 异常增强 -> 后置增强 。

3. 开启AOP

      在配置文件中使用@EnableAspectJAutoProxy注解开启AOP功能

在这里插入图片描述

4. 创建控制类

@RestController
@RequestMapping("test")
@Tag(name = "测试",description = "测试springMVC拦截器实现记录访问次数")
public class TestController {
    @GetMapping("getInfo/{id}")
    public String test(@PathVariable Integer id) {
        switch (id){
            case 1:
                return "1";
            case 2:
                return "2";
            default:
                return "3";
        }
    }
}

5. 测试

      在浏览器中输入 http://localhost:8080/test/getInfo/1 测试aop是否生效。
在这里插入图片描述
      console输出,AOP生效。

在这里插入图片描述
      over…
在这里插入图片描述

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐