Spring AOP 通过“面向切面编程”可以在指定的 controller、service、dao 层等,无感知无侵入性地嵌入逻辑;切面编程的方法参数主要是 JoinPoint
接口对象,那么针对被切面的相关信息如参数值、参数名称、方法名称、返回值、注解等都需要通过 JoinPoint
对象来获取。
参数值
@Before("pointSign()")
public void doBefore(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
...
}
通过如上方法,可以获取被切面方法的参数值,返回 Object[] 对象数组,数组的顺序与被切方法参数顺序一致。
java 基本类型的参数都会返回对应的封装类型,如 int 类型参数在这里返回 java.lang.Integer 类型。
参数名称
在 Java 8 之前,代码编译为 class 文件后,方法参数的类型固定,但是方法名称会丢失,方法名称会变成 arg0、arg1、…。从 Java 8 开始,在 class 文件中保留了参数名,所以在 java 8 开始也可以在 AOP 中获取参数名称。
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String[] parameterNames = methodSignature.getParameterNames();
方法名称
String methodName = joinPoint.getSignature().getName()
返回值
Spring AOP 获取被切面方法的返回值有两种方式,一个是在 @Around 环绕通知里获取,另一个是 @AfterReturning 里获取,具体如下:
@Pointcut("execution(public int org.demo.service.AOPService.demoAOP(..))")
public void pointSign() {}
@Around("pointSign()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) {
try {
// 调用目标方法,返回目标方法返回值
Object obj = proceedingJoinPoint.proceed();
System.out.println("doAround return type:" + obj.getClass());
System.out.println("doAround return value:" + obj);
return obj;
} catch (Throwable throwable) {
} finally {
}
return null;
}
@AfterReturning(returning = "ret", value = "pointSign()")
public void doAfterReturning(JoinPoint joinPoint, Object ret) {
// ret 也是目标方法返回值
System.out.println("doAfterReturning return type:" + ret.getClass());
System.out.println("doAfterReturning return value:" + ret);
}
注解
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);