Java 使用连接点调用(**.*(..),我是否可以将参数公开给通知(如果可用)?

Java 使用连接点调用(**.*(..),我是否可以将参数公开给通知(如果可用)?,java,refactoring,aspectj,pointcut,Java,Refactoring,Aspectj,Pointcut,在aspect中,我通过建议java.util.Set实例上的某些方法调用,特别是addObject和removeObject,来跟踪某些集合上的更改。由于更改不会反映在集合本身中,因此对Set.containsObject或Set.size的调用会返回错误的结果 因此,我希望截获对Set实例(add和remove除外)的所有方法调用,并将调用转发到我的最新集合 当然,我可以定义两个建议,使用不同的切入点,比如: // matches Collection.size(), Collection.

在aspect中,我通过建议java.util.Set实例上的某些方法调用,特别是addObject和removeObject,来跟踪某些集合上的更改。由于更改不会反映在集合本身中,因此对Set.containsObject或Set.size的调用会返回错误的结果

因此,我希望截获对Set实例(add和remove除外)的所有方法调用,并将调用转发到我的最新集合

当然,我可以定义两个建议,使用不同的切入点,比如:

// matches Collection.size(), Collection.isEmpty(), ...
* around(Collection c) : call(* Collection.*()) && target(c)
            && !remove(/*...*/) && !add(/*...*/) {
    if (notApplicable())
        return proceed(c);

    return proceed(getUpToDateCollection());
}

// matches Collection.contains(Object), ...
* around(Collection c, Object arg) : call(* Collection.*(*)) && target(c) && args(arg) 
            && !remove(/*...*/) && !add(/*...*/) {
    if (notApplicable())
        return proceed(c, arg);

    return proceed(getUpToDateCollection(), arg);
}
* around(Object[] args): call(* Collection.*(..)) && args(arr) {...}`
它是有效的,但它相当丑陋,我的建议的主体是相当类似的。所以我想把它们结合起来;有效地为两个切入点提供一个建议,如下所示:

// matches Collection.size(), Collection.isEmpty(), ...
* around(Collection c) : call(* Collection.*()) && target(c)
            && !remove(/*...*/) && !add(/*...*/) {
    if (notApplicable())
        return proceed(c);

    return proceed(getUpToDateCollection());
}

// matches Collection.contains(Object), ...
* around(Collection c, Object arg) : call(* Collection.*(*)) && target(c) && args(arg) 
            && !remove(/*...*/) && !add(/*...*/) {
    if (notApplicable())
        return proceed(c, arg);

    return proceed(getUpToDateCollection(), arg);
}
* around(Object[] args): call(* Collection.*(..)) && args(arr) {...}`
这可能吗?我觉得不是这样,因为在其中一个切入点中,我公开了参数,然后在建议中使用它,而在另一个切入点中没有参数,所以似乎不可能在封闭的建议中绑定潜在标识符。。。但我希望我忽略了什么,你也许能给我指出正确的方向。谢谢

只是为了记录在案。
可以编写一个公开参数的切入点,然后在不访问这些参数的通知中使用该切入点。与其将切入点表达式立即写入通知定义中,我始终更愿意明确定义切入点,仅通过切入点的名称和参数从通知中引用它

我不知道为什么这么多年后,这个问题在我的提要中以新的形式出现,但仍然没有答案,因此,我会回答:

您的假设是正确的,不能使用args绑定不存在的参数。 如果您确实想要一个通知正文,可以使用JoinPoint.getArgs..,但这会很难看,因为它涉及循环和强制转换,并且可能比使用两个切入点慢。如果操作错误,过宽的切入点也可能匹配过多的连接点。 我的建议(并非双关语)是将重复的代码分解成助手方法,并从AspectJ建议中调用它们。如果您还想计算出该部分,那么这些助手方法可能还需要一个ProceedingJoinPoint参数,以便调用ProceedingJoinPoint。但也要考虑可读性。这取决于你的具体情况。
如果您的代码实际上有点小,我可以用方面代码以更具体的方式回答。

我不理解这个答案。