如何使用AspectJ捕获所有新创建的类型或子类型Widget对象?

时间:2013-04-20 21:50:08

标签: java aspectj

为了获取所有新实例化的小部件,我尝试了以下代码

after(final Widget widget) : execution (* Widget+.new(..)) && this(widget) {
    ...
}

但每次有链式构造函数(同一类中的几个构造函数,相互引用)时它都会失败。

我需要收集在应用程序中创建的所有类型的小部件。我不能使用call代替execution,因为这意味着编织代码将成为调用代码的一部分,而不是Widget代码,这很麻烦,因为有很多参与这个项目的图书馆,这将使我必须编织所有这些以完成所描述的努力。

由于

编辑(更多信息)

考虑以下课程:

class A {
  private int i;

  public A(int i) {
    this.i = i;
    initialize();
  }

  public A() {
    this(0);
  }
}

after(final A a) : execution (* A+.new(..)) && this(a) {
  ...
}

//test
new A(0); //caught by the aspect and fine
new A(); //caught by the aspect twice, once for every constructor.

如果考虑A s的层次结构:

,情况会更糟
class B extends A {
  public B() {
    super();
  }

  public B(int i) {
    super(i);
  }
}

//test
new B(0); //caught by the aspect twice, once as B and once as A
new A(); //caught by the aspect thrice, once for B and twice for A

我只想捕获一次对象,并且只在对象完全构造之后(也就是说,它已经将“外部”构造函数运行到最后),作为注入到正在考虑的类中的方面代码不在它之外(因此call是不可接受的)。

有一个有趣的讨论我在AspectJ邮件列表上找到了另一个关于这个主题的讨论:http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg09651.html。它描述了一种可能的(非完整的,如果我没有错)解决方案,涉及某种堆栈分析。

EDIT2

这种简单的黑客似乎可以解决问题:

after(A a) : initialization(A+.new(..)) && this(a) {
    if (a.getClass() == thisJoinPoint.getSignature().getDeclaringType())
                //fully constructed object caught
}

1 个答案:

答案 0 :(得分:0)

在您的情况下,您应该能够使用初始化切入点。有关该切入点的更多信息,请参阅AspectJ docs。基本上,你应该做这样的事情:

after(final A a) : initialization (* A+.new(..)) && this(a) {
  ...
}

这里的好处是你可能会很棘手,并指定一个特定的构造函数。在以下情况中,仅匹配1-arg构造函数。 0-arg constrcutor不是。

initialization (* A+.new(int))