面向切面编程 JoinPoint 获取 方法签名、方法参数、目标对象 等

1. 概念介绍

  • 在 Spring AOP(面向切面编程)中,JoinPoint是一个非常重要的概念。它表示程序执行过程中的一个点,这个点可以是方法的调用、方法的执行、构造函数的调用等。简单来说,它是切面(Aspect)能够切入的地方。通过JoinPoint,可以获取到关于目标方法(被切面拦截的方法)的很多信息,如方法签名、方法参数、目标对象等。

2. 获取JoinPoint对象

  • 在切面的通知(Advice)方法中,可以将JoinPoint作为参数传入,从而获取相关信息。例如,在前置通知(Before Advice)中:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}

    @Before("serviceMethods()")
    public void logBeforeServiceMethod(JoinPoint joinPoint) {
        System.out.println("即将执行方法: " + joinPoint.getSignature().getName());
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println("方法参数: " + arg);
        }
    }
}
  • 在这个例子中,logBeforeServiceMethod方法接收一个JoinPoint对象作为参数。通过joinPoint.getSignature().getName()可以获取目标方法的名称,通过joinPoint.getArgs()可以获取目标方法的参数数组。

3.JoinPoint的主要信息获取方法

  • 获取方法签名(Signature)
  • 方法签名包含了方法的名称、返回值类型、参数类型等信息。可以通过joinPoint.getSignature()获取方法签名对象,然后使用该对象的方法来获取具体信息。例如:
Signature signature = joinPoint.getSignature();
String methodName = signature.getName();
Class<?> returnType = signature.getReturnType();
Class<?>[] parameterTypes = signature.getParameterTypes();
  • 这个方法在需要访问目标对象的状态或者其他属性时很有用,比如在事务管理切面中,可能需要检查目标对象的事务状态。
  • 获取代理对象(Proxy Object)
  • 有时候可能需要获取代理对象,可以通过joinPoint.getThis()方法来实现。在 AOP 中,代理对象是实际调用目标方法的对象。例如:
Object proxy = joinPoint.getThis();
// 对代理对象进行操作,如检查代理的类型等

4.在不同通知类型中的使用

  • 前置通知(Before):如前面的例子所示,可以在前置通知中使用JoinPoint来获取目标方法的信息,如方法名称、参数等,用于记录日志、进行参数验证等操作。
  • 后置通知(After):同样可以获取JoinPoint信息,用于记录目标方法执行后的状态。例如:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}

    @After("serviceMethods()")
    public void logAfterServiceMethod(JoinPoint joinPoint) {
        System.out.println("方法 " + joinPoint.getSignature().getName() + " 已执行");
    }
}
  • 返回通知(AfterReturning)和异常通知(AfterThrowing):在返回通知和异常通知中,JoinPoint也可以和其他返回值或者异常对象一起使用,来更全面地记录方法执行的情况。例如,在返回通知中:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturningServiceMethod(JoinPoint joinPoint, Object result) {
        System.out.println("方法 " + joinPoint.getSignature().getName() + " 返回结果: " + result);
    }
}
上一篇:Java8 新特性 —— Optional API 详解


下一篇:ImportError: numpy.core.multiarray failed to import