Spring AOP 计算一个特定方法被另一个方法调用的次数

发布于 2024-10-15 03:43:17 字数 390 浏览 4 评论 0原文

我有一个带有方法 rangeQuery() 的接口,我试图使用 Spring AOP 跨所有子类型进行分析。特别是,对于任何对 rangeQuery() 的调用,我想知道它在其主体的字段上调用另一个方法 distance() 次数。

我知道我可以编写一个方法来计算所有对距离的调用,如下所示:

@Before("execution(* *.distance(..))") 
public void count(JoinPoint joinPoint) {
    count++
}

但是,这不会捕获哪个 rangeQuery() 调用调用了它。

有什么想法吗?

I have an Interface with the method rangeQuery() which I am trying to profile across all subtypes, using Spring AOP. In particular, for any call to rangeQuery() I'd like to know how many times it calls another method distance() on a field from its body.

I know that I could write a method that counts all calls to distance as follows:

@Before("execution(* *.distance(..))") 
public void count(JoinPoint joinPoint) {
    count++
}

However, that would not capture which rangeQuery() call called it.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

剧终人散尽 2024-10-22 03:43:17

作为最后的手段,在上面的 @Before 建议中,您可以使用 Thread.currentThread.getStackTrace() 并查看调用者是否是 rangeQuery.

但是,您应该在堆栈跟踪中找到一些固定的“模式”来查找,而不仅仅是检查第 N 个位置来查看它是否是您正在寻找的方法。例如,您知道当时应该以某种给定顺序位于堆栈上的一系列方法,但允许出现任何其他中间堆栈元素。否则,代码中的任何更改都会使建议停止工作。

As a last resort, in the @Before advice above, you can make use of Thread.currentThread.getStackTrace() and see if the caller is rangeQuery.

However, you should find some fixed "pattern" to look for in the stack trace and not just check the Nth position to see if it's the method you're looking for. For example, a sequence of methods that you know should be on the stack at that time in some given order but allowing any other intermediate stack elements to occur. Otherwise, any change in your code would make the advice stop working.

于我来说 2024-10-22 03:43:17

您可能必须使用 @Around,而不是使用 @Before,它允许您使用 ProceedingJoinPoint 来获取源位置。

 @Around(" ..... ")
  public void test(ProceedingJoinPoint pjp) throws Throwable {

    SourceLocation sl = pjp.getSourceLocation();
    System.out.println(sl.getFileName());
    System.out.println(sl.getLine());
    System.out.println(sl.getWithinType());

    // allow through
    pjp.proceed();
  }

在你的情况下,听起来你可能需要call而不是execution,但Spring AOP似乎不支持call:-

其他切入点类型

完整的 AspectJ 切入点语言
支持额外的切入点
不支持的指示符
春天。这些是:打电话,
初始化、预初始化、
静态初始化、获取、设置、
处理程序、建议执行、代码内、
cflow、cflowbelow、if、@this 和
@incode。这些切入点的使用
切入点表达式中的指示符
Spring AOP 解释的结果是
在 IllegalArgumentException 中
抛出。

Instead of using @Before, you probably have to use @Around that allows you to use ProceedingJoinPoint to get the source location.

 @Around(" ..... ")
  public void test(ProceedingJoinPoint pjp) throws Throwable {

    SourceLocation sl = pjp.getSourceLocation();
    System.out.println(sl.getFileName());
    System.out.println(sl.getLine());
    System.out.println(sl.getWithinType());

    // allow through
    pjp.proceed();
  }

In you case, it sounds like you might need call instead of execution but it seems like call is not supported in Spring AOP:-

Other pointcut types

The full AspectJ pointcut language
supports additional pointcut
designators that are not supported in
Spring. These are: call,
initialization, preinitialization,
staticinitialization, get, set,
handler, adviceexecution, withincode,
cflow, cflowbelow, if, @this, and
@withincode. Use of these pointcut
designators in pointcut expressions
interpreted by Spring AOP will result
in an IllegalArgumentException being
thrown.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文