【问题标题】:spring AoP, pointcut expression for overloaded methods with same parameter typesspring AoP,具有相同参数类型的重载方法的切入点表达式
【发布时间】:2014-11-12 05:45:59
【问题描述】:

我已经为 cmets 上的 CRUD 操作定义了一个类。 read 方法被重载了。

class Comment{
    // method 1: returns all the comments by a user
    findAll(long userId, long subjectId, String param);

    // method 2: returns all the comments of all the users
    findAll(long subjectId, String param)
}

我试过的切入点表达式是

@Around("execution(* com.package..*Controller.findAll(..)) && args(userId,subjectId,..)")
public Object validateFindAll(final ProceedingJoinPoint proceedingJoinPoint, final long userId, final long subjectId) {
    // validate userId, if available
    // validate subjectId
}

问题:由于 userId 和 subjectId 的数据类型相同,点表达式应用于方法 2 时,会将参数值移动 1 位。这意味着,表达式不理解第一个参数 userId 未传递。相反,userId 将“subjectId”作为值,而 subjectId 将相邻参数“param”作为其值。

注意

  1. 我试图避免编写另一种方法,例如 findUserComments()。

  2. 我想保持整个应用程序的一致性。还有其他类具有类似的 CRUD 操作模式。

问题:是否可以定义一个适用于这两种方法的表达式,第一个参数 userId 是可选的?

编辑 - 解决方案 虽然我正在尝试以下解决方案中建议的不同方法,但我最终删除了方法 2。我在方法 1 中处理这种情况。

【问题讨论】:

    标签: spring aop spring-aop pointcut pointcuts


    【解决方案1】:

    您不能显式绑定 AspectJ 参数,然后期望它匹配不兼容的签名。因此,您的切入点将仅匹配 findAll(long, long, ..),即您的示例中的“方法 1”。您可以使用.. 指定可选参数,但不能将它们绑定到命名参数。

    例如,可以匹配这两种方法并通过args(.., subjectId, param) 绑定long subjectIdString param,因为可以预见这两个参数在签名的末尾是右对齐的。如果你想要任何可选的(因此是未绑定的)参数,你需要使用thisJoinPoint.getArgs()

    @Around("execution(* com.package..*Controller.findAll(..)) && args(.., subjectId, param)")
    public Object validateFindAll(
        final ProceedingJoinPoint thisJoinPoint,
        final long subjectId,
        final String param
    ) {
        if (thisJoinPoint.getArgs().length == 3)
            System.out.println(thisJoinPoint + " -> " + thisJoinPoint.getArgs()[0] + ", " + subjectId + ", " + param);
        else
            System.out.println(thisJoinPoint + " -> " + subjectId + ", " + param);
        // (...)
    }
    

    虽然getArgs() 是动态的,但它可能比参数绑定慢,因为它使用反射。也许有两个切入点毕竟不是那么糟糕。如果您的通知方法在proceed() 之前/之后做了复杂的事情,您仍然可以将这些事情分解到辅助方法中并从两个建议中调用它们。

    【讨论】:

    • 那你为什么不接受我的答案而不是另一个?
    【解决方案2】:

    问题实际上与方法平均加载有关。因为,您传递的是 long userId 和 long subjectId AOP 将始终尝试匹配这些参数。解决方案可能是

    1) 为其他参数创建另一个切入点,即 1 表示 long、long 和 other 表示 long、String

    2) 在开头使用可变参数签名,例如

     @Around("execution(* com.org..findAll(..)) && args(..,subjectId,param)")
    public Object validateFindAll(final ProceedingJoinPoint joinPoint, final long userId, final long subjectId) {
    
     }
    

    而不是在开始时使用可变参数。然后你可以使用 getArgs() 方法来计算参数。 这是一个简单的解决方案,但可能会减慢您的处理速度。

    3) 尽管作为一个设计问题,我建议将所有参数封装在一个对象中并传递它。而不是传递多个参数。将来也会对您有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多