在 Spring AOP 中是否可以有多个具有不同参数的切入点?

Is it possible to have multiple pointcuts with different arguments in Spring AOP?

我有一个带有多个切入点的建议方法。是否可以有不同的论点?

   @Around("execution(* com.admin.web.controller.*.*.*(javax.servlet.http.HttpServletRequest,com.admin.model.PortalRequestTransaction)) && args(request,portalRequestTransaction)"
        + " || execution(* com.admin.web.controller.BaselineImporterController.*(javax.servlet.http.HttpServletRequest,..)) && args(request)")
public Object auditAround(ProceedingJoinPoint joinPoint, HttpServletRequest request,
                          PortalRequestTransaction portalRequestTransaction) throws Throwable { // some code here }

例如,是否有可能第一个切入点有 2 个参数,而第二个切入点只有一个参数,第二个作为 null 传递? 如果这不可能,最好的解决方案是什么?

是的,您的建议中可以有多个 point-cuts,这是使用以下通用语法完成的:

@AdviceType("execution(point-cut1) || execution(point-cut2) || execution(point-cut3)")
public void foo(){}

请注意,@AdviceTypepoint-cutX 是概念名称,您应该根据您的建议和切入点[s]分别更改它们。

实现此目的的一种方法是使用 JoinPoint.getArgs() 将方法参数作为对象数组获取。这就涉及到反思了。

实现此目的的示例代码如下

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class TestAspect {
    
    @Pointcut("execution(* com.admin.web.controller.*.*.*(javax.servlet.http.HttpServletRequest,com.admin.model.PortalRequestTransaction))")
    public void requestNTransaction() {}
    
    @Pointcut("execution(* com.admin.web.controller.BaselineImporterController.*(javax.servlet.http.HttpServletRequest,..))")
    public void requestAsFirstArg() {}

    @Around("requestNTransaction() || requestAsFirstArg()")
    public Object auditAround(ProceedingJoinPoint pjp) throws Throwable {
        // get the signature of the method to be adviced
        System.out.println(pjp.getSignature());
        Object[] args = pjp.getArgs();
        for(Object arg:args) {
            // use reflection to identify and process the arguments
            System.out.println(arg.getClass());
        }
        return pjp.proceed();
    }

}

注:

  1. 作为切入点签名的单个方法。 Spring documentation
  2. ProceedingJoinPoint 对于 @Around 建议类型