AspectJ:跟踪新对象初始化
AspectJ: track new object initialization
我正在尝试了解 AspectJ。我想尝试计算项目中的所有对象初始化(它们是从我指定的 classes 初始化的,而不是一些 Java- 内部的),我真的不知道该怎么做这个。
假设我有 classes 称为 A 和 B,其中 A 有子classes Aa 和 Ab,B 有子classes Ba 和 Bb,以及 Bb有子class Bba。我希望我的方面跟踪以这些 classes 作为基础创建的对象的每一次初始化,但我真的不明白如何正确地做到这一点(尽管这应该有点简单)。到目前为止,我有类似的东西:
public aspect AspectCounter {
private int objects = 0;
pointcut countObjects() : initialization(A.new(..)) || initialization(B.new(..));
pointcut printObjects() : call(* Test.printCounter(..));
after() : countObjects() {
objects++;
}
after() : printObjects() {
System.out.println(objects);
}
}
至少,它打印了我创建的正确数量的 A 和 B(我没有使用 B*.new(..),因为按照我的理解,它会跟踪任何Bba 的初始化三次,在这种情况下我不想要)。
它现在的工作方式是我有一个 Test class ,它可以测试东西,在我完成测试之后,我只是调用一个空的 printCounter 方法,它实际上并没有做任何事物。它似乎有效并且确实为我提供了正确数量的对象,但我确信有更好的方法可以做到这一点。我真的不喜欢空方法。
您不能在 *.new(..)
上使用 initialization
、preinitialization
或 execution
切入点执行此操作,因为它们的执行顺序不同。由于 JVM 的工作方式,它们并不像您想象的那样嵌套,而是按顺序执行。我已经详细解释了这一点 here,包括示例代码和日志输出。所以你只剩下使用 call
切入点的选项。这是一个例子:
package de.scrum_master.app;
public class A {}
package de.scrum_master.app;
public class Aa extends A {}
package de.scrum_master.app;
public class Ab extends A {}
package de.scrum_master.app;
public class B {}
package de.scrum_master.app;
public class Ba extends B {}
package de.scrum_master.app;
public class Bb extends B {}
package de.scrum_master.app;
public class Bba extends Bb {}
驱动申请:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new A();
new Aa();
new Ab();
new B();
new Ba();
new Bb();
new Bba();
}
}
看点:
package de.scrum_master.aspect;
import de.scrum_master.app.A;
import de.scrum_master.app.B;
public aspect InstanceCreationCounter {
private static int count;
after() : call(A+.new(..)) || call(B+.new(..)) {
System.out.printf("%4d %s%n", ++count, thisJoinPoint);
}
}
控制台日志:
1 call(de.scrum_master.app.A())
2 call(de.scrum_master.app.Aa())
3 call(de.scrum_master.app.Ab())
4 call(de.scrum_master.app.B())
5 call(de.scrum_master.app.Ba())
6 call(de.scrum_master.app.Bb())
7 call(de.scrum_master.app.Bba())
我想这就是你想要的。
警告:您需要控制所有调用代码并将方面编织到其中才能使其工作。
我正在尝试了解 AspectJ。我想尝试计算项目中的所有对象初始化(它们是从我指定的 classes 初始化的,而不是一些 Java- 内部的),我真的不知道该怎么做这个。
假设我有 classes 称为 A 和 B,其中 A 有子classes Aa 和 Ab,B 有子classes Ba 和 Bb,以及 Bb有子class Bba。我希望我的方面跟踪以这些 classes 作为基础创建的对象的每一次初始化,但我真的不明白如何正确地做到这一点(尽管这应该有点简单)。到目前为止,我有类似的东西:
public aspect AspectCounter {
private int objects = 0;
pointcut countObjects() : initialization(A.new(..)) || initialization(B.new(..));
pointcut printObjects() : call(* Test.printCounter(..));
after() : countObjects() {
objects++;
}
after() : printObjects() {
System.out.println(objects);
}
}
至少,它打印了我创建的正确数量的 A 和 B(我没有使用 B*.new(..),因为按照我的理解,它会跟踪任何Bba 的初始化三次,在这种情况下我不想要)。 它现在的工作方式是我有一个 Test class ,它可以测试东西,在我完成测试之后,我只是调用一个空的 printCounter 方法,它实际上并没有做任何事物。它似乎有效并且确实为我提供了正确数量的对象,但我确信有更好的方法可以做到这一点。我真的不喜欢空方法。
您不能在 *.new(..)
上使用 initialization
、preinitialization
或 execution
切入点执行此操作,因为它们的执行顺序不同。由于 JVM 的工作方式,它们并不像您想象的那样嵌套,而是按顺序执行。我已经详细解释了这一点 here,包括示例代码和日志输出。所以你只剩下使用 call
切入点的选项。这是一个例子:
package de.scrum_master.app;
public class A {}
package de.scrum_master.app;
public class Aa extends A {}
package de.scrum_master.app;
public class Ab extends A {}
package de.scrum_master.app;
public class B {}
package de.scrum_master.app;
public class Ba extends B {}
package de.scrum_master.app;
public class Bb extends B {}
package de.scrum_master.app;
public class Bba extends Bb {}
驱动申请:
package de.scrum_master.app;
public class Application {
public static void main(String[] args) {
new A();
new Aa();
new Ab();
new B();
new Ba();
new Bb();
new Bba();
}
}
看点:
package de.scrum_master.aspect;
import de.scrum_master.app.A;
import de.scrum_master.app.B;
public aspect InstanceCreationCounter {
private static int count;
after() : call(A+.new(..)) || call(B+.new(..)) {
System.out.printf("%4d %s%n", ++count, thisJoinPoint);
}
}
控制台日志:
1 call(de.scrum_master.app.A())
2 call(de.scrum_master.app.Aa())
3 call(de.scrum_master.app.Ab())
4 call(de.scrum_master.app.B())
5 call(de.scrum_master.app.Ba())
6 call(de.scrum_master.app.Bb())
7 call(de.scrum_master.app.Bba())
我想这就是你想要的。
警告:您需要控制所有调用代码并将方面编织到其中才能使其工作。