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…