使用连接点调用(* *.*(..)),我可以将参数公开给建议(如果可用)吗?
在我的方面,我通过建议对 java.util.Set
实例的某些方法调用来跟踪某些集合的更改,特别是 add(Object)
和 remove(对象)
。 由于更改不会反映在集合本身中,因此调用 Set.contains(Object)
或 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) {...}`
这可能吗? 我感觉不是,因为在一个切入点中我公开了参数(然后在建议中使用它),而在另一个切入点中没有参数,所以似乎不可能在封闭的建议中绑定“潜在标识符” ...但我希望我忽略了一些事情,你也许能够为我指明正确的方向。 谢谢!
With my aspect, I track the changes on certain collections by advising certain method calls on instances of java.util.Set
, notably add(Object)
and remove(Object)
. Since the changes are not reflected in the collection itself, invocations of Set.contains(Object)
or Set.size()
return wrong results.
Therefore I want to intercept all method calls to instances of Set (except add
and remove
), and forward the calls to my up-to-date collection.
Of course I could define two advices, using different pointcuts, something like this:
// 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);
}
It works, but it's pretty ugly, the bodies of my advices being quite analogous. So I would like to "combine" them; effectively having a single advice that be woven for both pointcuts, much like this:
* around(Object[] args): call(* Collection.*(..)) && args(arr) {...}`
Is this possible at all? I have the feeling it's not, because in one of the pointcuts I expose the argument (and subsequently use it in the advice) and in the other there is no argument, so it seems impossible to bind the "potential identifier" in the enclosing advice... But I'm hoping that I've overlooked something and you might be able to point me in the right direction. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
仅供记录。
可以编写一个公开参数的切入点,然后在不访问这些参数参数的通知中使用此切入点。 我总是更喜欢显式定义切入点,而不是立即将切入点表达式写入建议定义中,仅通过切入点的名称(和参数)从建议中引用它
just for the record.
it is possible to write a pointcut which exposes an argument, and then use this pointcut in advice which doesn't access these argument parameter. Instead of writing the pointcut expression immediately into the advice definition, I'd allways prefer to define the pointcut explicitly, referring to it from the advice just by the pointcut's name (and arguments)
我不知道为什么这个问题在我的提要中作为“新”这么多年出现,但它仍然没有答案,所以我会回答:
args()
为了绑定一个不存在的参数。ProceedingJoinPoint
参数,以便在您还想提取该部分时调用proceed()
。 但也要考虑可读性。 这始终取决于您的具体情况。如果您的代码实际上有点SSCCE,我可以以更具体的方式(使用方面代码)回答。
I have no idea why this question has popped up in my feed as "new" after so many years, but it is still unanswered, so I will answer:
args()
in order to bind a non-existent argument.JoinPoint.getArgs(..)
, but it would be ugly (as in involving loops and casts) and potentially slower than having two pointcuts. A too broad pointcut would also potentially match too many joinpoints if done wrong.ProceedingJoinPoint
parameter in order to callproceed()
upon it if you also want to factor out that part. But think about readability, too. It always depends on your concrete case.I could answer in a more concrete way (with aspect code) if your code was actually a litte SSCCE.