- @Around注解用于修饰Around增强处理,就是调用切面类中的通知方法
参数 |
描述 |
value |
要绑定通知的切入点表达式 |
argNames |
在没有调试信息的情况下编译时,或在运行时解释切入点时,通知声明中使用的任何参数的名称都不可用 |
- 环绕通知对应的方法必须有返回值,使用ProceedingJoinPoint参数,而不是JoinPoint
- @Around可以自由选择增强动作与目标方法的执行顺序,也就是说可以在增强动作前后,甚至过程中执行目标方法。这个特性的实现在于,调用ProceedingJoinPoint参数的procedd()方法才会执行目标方法。
- @Around可以改变执行目标方法的参数值,也可以改变执行目标方法之后的返回值。
- Around增强处理有以下特点:
- 当定义一个Around增强处理方法时,该方法的第一个形参必须是 ProceedingJoinPoint 类型(至少一个形参)。
在增强处理方法体内,调用ProceedingJoinPoint的proceed方法才会执行目标方法:这就是@Around增强处理可以完全控制目标方法执行时机、如何执行的关键;如果程序没有调用ProceedingJoinPoint的proceed方法,则目标方法不会执行。
- 调用ProceedingJoinPoint的proceed方法时,还可以传入一个Object[ ]对象,该数组中的值将被传入目标方法作为实参——这就是Around增强处理方法可以改变目标方法参数值的关键。
这就是如果传入的Object[ ]数组长度与目标方法所需要的参数个数不相等,或者Object[ ]数组元素与目标方法所需参数的类型不匹配,程序就会出现异常。
- @Around功能虽然强大,但通常需要在线程安全的环境下使用。因此,如果使用普通的Before、AfterReturning就能解决的问题,就没有必要使用Around了。
如果需要目标方法执行之前和之后共享某种状态数据,则应该考虑使用Around。
尤其是需要使用增强处理阻止目标的执行,或需要改变目标方法的返回值时,则只能使用Around增强处理了。
示例
- 定义接口类
package com.example.demo;
@RestController
@RequestMapping(value = "/permission")
public class TestController {
@RequestMapping(value = "/check", method = RequestMethod.POST)
@PermissionsAnnotation()
public JSONObject getGroupList(@RequestBody JSONObject request) {
return JSON.parseObject("{\"message\":\"SUCCESS\",\"code\":200,\"data\":" + request + "}");
}
}
- 定义切面类
@Aspect @Component @Order(1) public class PermissionAdvice {
@Pointcut("@annotation(com.example.demo.PermissionsAnnotation)") private void permissionCheck() { }
@Around("permissionCheck()") public Object permissionCheck(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("===================开始增强处理===================");
//获取请求参数,详见接口类 Object[] objects = joinPoint.getArgs(); Long id = ((JSONObject) objects[0]).getLong("id"); String name = ((JSONObject) objects[0]).getString("name"); System.out.println("id1->>>>>>>>>>>>>>>>>>>>>>" + id); System.out.println("name1->>>>>>>>>>>>>>>>>>>>>>" + name);
// 修改入参 JSONObject object = new JSONObject(); object.put("id", 8); object.put("name", "lisi"); objects[0] = object;
// 将修改后的参数传入,joinPoint.proceed()为目标对象执行原结果 return joinPoint.proceed(objects); } }
|
运行结果:
- 同样使用JMeter调用接口,传入参数:{"id":-5,"name":"admin"},响应结果表明:@Around截取到了接口的入参,并使接口返回了切面类中的结果。