如何定义一个AspectJ切入点,以选择具有特定注释的类的所有构造函数?

3

以下是注释:

@Target(value = ElementType.TYPE)
@Retention(value = RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnotation {
    String name();
}

这里有一个带注释的类:

@MyAnnotation(name="foo")
public class ClassA {
    public ClassA() {
        // Do something
    }
}

这是第二个带注解的类:

@MyAnnotation(name="bar")
public class ClassB {
    public ClassB(String aString) {
        // Do something
    }
}

我正在寻找一个AspectJ切入点,它可以正确匹配ClassA和ClassB的构造函数,同时不匹配任何未被MyAnnotation注解的其他类的构造函数。
3个回答

6

您的切入点应该长成这样:

execution((@MyAnnotation *).new(..))

如果注解在另一个包中:
execution((@de.scrum_master.aop.demo.MyAnnotation *).new(..))

如果您不想完全限定包名:

execution((@*..MyAnnotation *).new(..))

编辑: 好的,以下是有关您在评论中提出的问题的更多信息:

构造函数执行没有返回值可以在其中捕获

after() returning(Object myObject) : myJoinpoint()

这仅适用于方法。所以请使用:
after(Object myObject) returning : myJoinpoint() && this(myObject)

如果你确实需要构造对象以满足特定需求,那么可以使用以下方式。


你试过这个吗?我问这个是因为我尝试在构造函数上定义执行连接点,结果收到了一个无法应用的警告。文档提供了使用call()的构造函数切入点原语的语法,但没有execution()等效项。 - PineForest
如果您愿意,请访问我的主页(请查看我的个人资料),找到在线聊天并与我交换电子邮件地址。如果我看到完整的代码,也许我可以帮助您。或者只需使用联系表格。哦,顺便说一下:您看到内部括号了吗? - kriegaex
前面示例中缺少注释的资格是有意为之。 - PineForest
感谢您对此的耐心等待。编译时没有警告。现在我得到了一个"org.aspectj.lang.NoAspectBoundException",针对--> after() returning: execution(*.new()) { // things to do }。 - PineForest
我已经更新了我的回答。但很抱歉,这个讨论到此为止。按照建议联系我,并让我看看你的完整代码。只有一点点信息是不够的,只会在这里垃圾邮件讨论。 - kriegaex
显示剩余5条评论

2

以下是kriegaex提出的完整可行解决方案:

public aspect AnnotationTests {
  public aspect AnnotationTests {
    after(Object myObject) returning : execution((@MyAnnotation *).new(..))
        && this(myObject) {
      System.out.println("Object class name: " + myObject.getClass().getName());
    }
  }
}

@MyAnnotation(name="foo")
public class ClassA {
  public ClassA() {
    // Do something
  }

  public static void main(String[] args) {
    ClassA classA = new ClassA();
    ClassB classB = new ClassB("");
    if (classA.getClass().getName().equals(classB.getClass().getName())) {
      throw new RuntimeException("Big problems!");
    }
  }
}

@MyAnnotation(name="bar")
public class ClassB {
  private final String aString;

  public ClassB(String aString) {
    this.aString = aString;
  }
}

这就是你的解决方案。与上面的许多片段唯一的区别在于它在此处以完整形式呈现。我只能猜测,让我检查你的回复可能有一定的价值。如果是这种情况,请将其复制并粘贴到您的回复中,我将乐意删除此内容并再次检查您的回复。 - PineForest
好的。谢谢您的反馈。我已经更新了我的“选定”答案,以便您获得应有的认可。 - PineForest

0

以下代码可以工作,但不被 kriegaex 推荐。如果需要,这里提供可能被重新利用的材料。

这是我第一个解决问题的方案,部分使用了 initialization() 切入点原语。

public aspect AnnotationTests {
  private pointcut genericConstructor(): initialization(*.new(..));
  private pointcut withinMyAnnotation(): @within(MyAnnotation);
  private pointcut constructorInAnnotatedClass(): genericConstructor()
      && withinMyAnnotation();

  before(): constructorInAnnotatedClass() && !cflowbelow(constructorInAnnotatedClass()) {
    final Object objectInstance = thisJoinPoint.getTarget();
    System.out.println("Object class name at join point: "
        + objectInstance.getClass().getName());
  }
}

@MyAnnotation(name="foo")
public class ClassA {
  public ClassA() {
    // Do something
  }

  public static void main(String[] args) {
    ClassA classA = new ClassA();
    ClassB classB = new ClassB("");
    if (classA.getClass().getName().equals(classB.getClass().getName())) {
        throw new RuntimeException("Big problems!");
    }
  }
}

@MyAnnotation(name="bar")
public class ClassB {
  private final String aString;

  public ClassB(String aString) {
    this.aString = aString;
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接