我已经在评论中为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得到了#subject; subjectId'作为值,subjectId得到相邻的参数' param'作为它的价值。
注意
我试图避免编写另一种方法,如findUserComments()。
我想在整个应用程序中保持一致性。还有其他类具有类似的CRUD操作模式。
问题:是否可以定义适用于两个方法的表达式,第一个参数userId是可选的?
编辑 - 解决方案 当我在下面的解决方案中提出不同的方法时,我终于删除了方法2.我在方法1中处理了这种情况。
答案 0 :(得分:2)
您无法显式绑定AspectJ参数,然后希望它与不兼容的签名匹配。因此,您的切入点仅匹配findAll(long, long, ..)
,即"方法1"在你的例子中。您可以使用..
指定可选参数,但不能将它们绑定到命名参数。
例如,可以匹配两种方法并通过long subjectId
绑定String param
和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()
之前/之后做了复杂的事情,你仍然可以将这些事情考虑在辅助方法中并从两个建议中调用它们。
答案 1 :(得分:0)
问题实际上与方法有关。因为,你传递的是long userId和long subjectId,AOP总是会尝试匹配这些参数。解决方案可能是
1)为其他参数创建另一个切入点,例如1表示long,long,其他表示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)虽然作为一个设计问题,我建议将所有参数封装在一个对象中并传递它。而不是传递多个参数。它也将在未来帮助你。