1

我有一些(静态)Java 方法。

我有一个切入点来执行这些方法中的任何一个:

pointcut calculation() : execution(* myMethod_*(..));

现在我想分别测量每次执行的时间。问题是执行可能随时触发,而其他执行仍在运行。我考虑了两个建议,before()after(),它们识别呼叫者来管理不同呼叫者的计时器。

before() : calculation() {

}

after() : calculation() {

}

我该如何实施?

4

3 回答 3

2

around() 建议应该有效:

   Object around() : calculation() {
        long start = System.nanoTime();
        Object result = proceed();
        long end = System.nanoTime();
        logger.info(String.format("%s took %d ns", thisJoinPointStaticPart.getSignature(),
                (end - start)));
        return result;
    }
于 2012-08-03T17:31:37.147 回答
1

我无法评论 Biju 的答案,所以我正在创建一个新答案:

您询问:

有一个问题:“建议 [...] 尚未应用 [Xlint:adviceDidNotMatch]” - 切入点似乎与 Java 方法不再匹配

嗯,应该怎么搭配?在执行你的静态方法(你自己提到过)时没有this对象,所以切入点应该是call()而不是execution(). 这是我为您创建的完整代码示例以进行演示:

应用类:

package de.scrum_master.aspectj.sample;

import java.util.Random;

public class Dummy {
    static Random random = new Random();

    static void myMethod_one() throws InterruptedException {
        Thread.sleep(random.nextInt(1000));
    }

    static String myMethod_two(int dummy) throws InterruptedException {
        Thread.sleep(random.nextInt(1000));
        return "dummy";
    }

    static int myMethod_three(double foo, String... dummy) throws InterruptedException {
        Thread.sleep(random.nextInt(1000));
        return -1;
    }

    public static void main(String[] args) throws InterruptedException {
        // We have no "this" here (static method), so advice is not applied
        myMethod_two(5);
        myMethod_one();
        myMethod_three(7.7, "foo", "bar");

        // Now let's create an object, so we have "this"
        new Dummy().doStuff();
    }

    void doStuff() throws InterruptedException {
        // Here advice is applied because we have "this"
        myMethod_one();
        myMethod_two(5);
        myMethod_one();
        myMethod_three(7.7, "foo", "bar");
        myMethod_three(3.3, "zot", "baz");
        myMethod_two(11);
    }
}

时序方面:

package de.scrum_master.aspectj.sample;

aspect TimingAspect {
    pointcut calculation(Object thisObject) :
        call(* myMethod_*(..)) && this(thisObject);

    Object around(Object thisObject) : calculation(thisObject) {
        long start = System.nanoTime();
        Object result = proceed(thisObject);
        long end = System.nanoTime();
        System.out.println(String.format(
            "%s (this = %s) took %d ns",
            thisJoinPointStaticPart.getSignature(),
            thisObject,
            end - start
        ));
        return result;
    }
}
于 2012-08-10T11:08:39.960 回答
0

最好的方法是用一个具有开始时钟和结束时钟的对象来包装每个方法。您可以使用:

System.nanoTime();

保存开始和结束时间。因此,您的通话前后可以设置开始和结束时间值。或者您可以将它们包装到一个运行命令中,该命令设置开始,运行方法,然后设置结束。

通过将方法包装在一个对象中,您可以将时序控制抽象到该对象,并根据需要并行执行任意数量的操作——每个都负责为自己的方法计时。

于 2012-08-03T17:24:18.373 回答