3

我已经为评论上的 CRUD 操作定义了一个类。读取方法被重载。

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 中处理这种情况。

4

2 回答 2

2

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

例如,可以同时匹配方法和 bindlong subjectIdString paramvia,args(.., subjectId, 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(),您仍然可以将这些事情分解为辅助方法并从两个建议中调用它们。

于 2014-11-12T10:19:43.017 回答
0

问题实际上与方法平均加载有关。因为,您传递的是 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)虽然作为一个设计问题,我建议将所有参数封装在一个对象中并传递它。而不是传递多个参数。将来也会对您有所帮助。

于 2014-11-12T10:28:16.823 回答