如果我需要使用 AspectJ 跟踪创建对象的时间,我是否捕获对构造函数的调用、正在执行的构造函数或对象初始化?这三个都有不同的语法:pointcut: call
,pointcut: execution
和pointcut: initialization
, 分别。
这三者之间有什么区别,哪一个最适合使用?
如果我需要使用 AspectJ 跟踪创建对象的时间,我是否捕获对构造函数的调用、正在执行的构造函数或对象初始化?这三个都有不同的语法:pointcut: call
,pointcut: execution
和pointcut: initialization
, 分别。
这三者之间有什么区别,哪一个最适合使用?
我在这里回答了一个类似的问题:如何横切带注释的方法和构造函数?
也许这有助于澄清安德鲁已经指出的内容。答案包含一个带有解释的小代码示例。
这 3 个切入点是重叠的,但具有不同的语义。来自AspectJ 编程指南:
由于我不确定您要做什么,因此我无法建议哪种方法最有意义,但是如果您想找出创建对象需要多少时间,那么使用执行切入点可以最有意义的。
为了更好地理解您的切入点将解决的连接点,这个简单的示例可以帮助您:
class C {
public void foo() {
System.out.println("foo");
}
}
public class Main {
public static void main(String[] args) {
C c = new C();
c.foo();
}
}
现在让我们有一个方面,它将打印所有可能的连接点,这些连接点可以通过之前和之后的建议进行更改:
public aspect MyAspect {
pointcut Anything() :
cflow(!within(MyAspect)) && !within(MyAspect);
before() : Anything() {
System.out.println("before " + thisJoinPoint);
}
after() : Anything() {
System.out.println("after " + thisJoinPoint);
}
}
产生以下输出:
...
before call(C()) // <-- call to constructor, new C()
before staticinitialization(C.<clinit>)
after staticinitialization(C.<clinit>)
before preinitialization(C())
after preinitialization(C())
before initialization(C())
before execution(C()) // <-- actual execution of constructor
after execution(C())
after initialization(C())
after call(C()) // <-- after call to constructor
...
因此,如果您将对象的初始化时间视为从调用构造函数到执行返回到调用它的同一范围的时间,这可能是一种方法:
public aspect ConstructionTiming {
private long startTime, endTime;
before() : call(C.new(..)) {
startTime = System.nanoTime();
}
after() : call(C.new(..)) {
endTime = System.nanoTime();
System.out.println("construction took " +
(endTime - startTime)/1e6 + "ms");
}
}
在我的情况下输出construction took 0.64879ms