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(..) 上使用 initializationpreinitializationexecution 切入点执行此操作,因为它们的执行顺序不同。由于 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())

我想这就是你想要的。

警告:您需要控制所有调用代码并将方面编织到其中才能使其工作。