我有一些(静态)Java方法。
我有一个切入点可以触发任何这些方法的执行:
pointcut calculation() : execution(* myMethod_*(..));
现在我想分别测量每次执行的时间。
问题是执行可能随时触发,而其他执行仍在运行。
我考虑了两个建议,before()
和after()
,它们可以识别呼叫者以管理不同呼叫者的定时器。
before() : calculation() {
}
after() : calculation() {
}
我该如何实现?
答案 0 :(得分: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;
}
答案 1 :(得分: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;
}
}
答案 2 :(得分:0)
最好的方法是使用具有开始时钟和结束时钟的对象包装每个方法。您可以使用:
System.nanoTime();
保存开始和结束时间。因此,您的前后调用可以设置开始和结束时间值。或者你可以将它们包装成一个运行命令,它设置start,运行方法,然后设置end。
通过将方法包装在一个对象中,您可以将时序控件抽象到该对象,并根据需要并行执行多个操作 - 每个都负责为自己的方法计时。