使用连接点调用(* *。*(..)),如果可用,我可以将参数公开给建议吗?

时间:2009-01-08 15:40:28

标签: java refactoring aspectj pointcut

根据我的方面,我通过建议对java.util.Set,特别是add(Object)remove(Object)的实例进行某些方法调用来跟踪某些集合的更改。由于更改未反映在集合本身中,因此Set.contains(Object)Set.size()的调用会返回错误的结果。

因此,我希望拦截对Set实例的所有方法调用(addremove除外),并将调用转发给我的最新集合。

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

// 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) {...}`

这有可能吗?我感觉不是,因为在其中一个切入点我暴露了参数(并随后在建议中使用它)而在另一个中没有参数,所以似乎不可能在封闭的建议中绑定“潜在的标识符” ......但我希望我忽略了一些东西,你可能会指出我正确的方向。谢谢!

2 个答案:

答案 0 :(得分:0)

仅供记录。
可以写一个暴露一个参数的切入点,然后在不访问这些参数参数的通知中使用这个切入点。我不是直接将切入点表达式写入通知定义,而是总是更明确地定义切入点,仅通过切入点的名称(和参数)从建议中引用它。

答案 1 :(得分:0)

我不知道为什么这个问题多年后在我的Feed中作为“新”出现了,但它仍然没有答案,所以我会回答:

  • 您的假设是正确的,您不能使用args()来绑定不存在的参数。
  • 如果你绝对想拥有一个建议体,你可以使用JoinPoint.getArgs(..),但它会很丑陋(如涉及循环和强制转换),并且可能比有两个切入点慢。如果做错了,过于宽泛的切入点也可能会匹配太多的连接点。
  • 我的建议 - 没有双关语意思 - 实际上是将重复的代码分解为辅助方法,并从两个AspectJ建议中调用它们。也许这些辅助方法还需要一个ProceedingJoinPoint参数,以便在您想要分解该部分时调用proceed()。但是也要考虑可读性。它总是取决于你的具体情况。

如果您的代码实际上是一个小小的SSCCE,我可以用更具体的方式(使用宽高比代码)回答。