【SpringAOP】JoinPoint和ProceedingJoinPoint详解

1. JoinPoint

Joinpoint是指在应用程序执行过程中可以被拦截的特定点。在AOP中,Joinpoint代表了程序执行的某个具体位置,比如方法的调用、异常的抛出等。AOP框架通过拦截这些Joinpoint来插入额外的逻辑,实现横切关注点的功能。
我们可以通过JoinPoint获取到除了异常参数对象和返回值之外的所有信息。
获取代理信息方法:

MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取代理方法的信息
String methodName = signature.getName(); // 获取方法名
Class<?> returnType = signature.getReturnType(); // 获取返回类型
Class<?>[] parameterTypes = signature.getParameterTypes(); // 获取参数类型数组

获取方法参数:

Object[] args = joinPoint.getArgs();

获取执行方法的对象:

Object target = joinPoint.getTarget();

ProceedingJoinPoint简介

在Spring AOP中,ProceedingJoinPoint是JoinPoint的子接口,它专门用于环绕通知(Around advice)。ProceedingJoinPoint包含了被通知方法的执行信息,同时可以访问被通知方法的信息和参数。可以通过使用ProceedingJoinPoint接口来实现更加灵活和精细的环绕通知逻辑。
使用方式与JoinPoint一致。
示例:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("Method " + methodName + " is called with arguments: " + Arrays.toString(args));
    }

    @AfterReturning(pointcut = "execution(* com.example.service.*.*(..))", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Method " + methodName + " returned with value: " + result);
    }

    @AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))", throwing = "ex")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Method " + methodName + " threw exception: " + ex.getMessage());
    }

    @Around("execution(* com.example.service.*.*(..))")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Entering method " + methodName);

        try {
            Object result = joinPoint.proceed();
            System.out.println("Exiting method " + methodName + " with result: " + result);
            return result;
        } catch (Throwable ex) {
            System.out.println("Exception in method " + methodName + ": " + ex.getMessage());
            throw ex;
        }
    }
}

execution(* com.example.service..(…)) 用来指定想要匹配的是方法执行的连接点。也就是说,只有当这些方法被执行时,才会触发相应的通知(Advice)。

  • (返回类型):
    第一个星号表示任意返回类型。这意呸着该表达式将匹配所有无论其返回值为何种类型的符合条件的方法。
    com.example.service: 这是指定的方法所在的包名。此表达式只匹配位于 com.example.service 包内的类中的方法。
  • (类名):
    第二个星号代表任意类名。这意味着该表达式会匹配 com.example.service 包内所有类中的方法,而不仅仅是特定的一个或几个类。
  • (方法名):
    第三个星号表示任意方法名。因此,不管方法叫什么名字,只要它符合前面的条件(即在 com.example.service 包中的任意类中),都会被匹配到。
  • (…) (参数列表):
    圆括号内的两个点号表示任意数量和类型的参数。这意味着无论方法接受多少个参数,或者参数的具体类型是什么,都将被匹配。

你可能感兴趣的:(spring)