How to define an aspectj pointcut that picks out all constructors of a class that has a specific annotation?

老子叫甜甜 提交于 2019-12-31 02:14:06

问题


Here is the annotation:

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

Here is one annotated class:

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

Here is a second annotated class:

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

I am looking for an aspectj pointcut that correctly matches the constructors for ClassA and ClassB while not matching any other constructor for any other class NOT annotated by MyAnnotation.


回答1:


Your pointcut should look like this:

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

If the annotation is in another package:

execution((@de.scrum_master.aop.demo.MyAnnotation *).new(..))

Or if you do not want to fully qualify the package:

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

Edit: Okay, some more info about your question in the comment:

Constructor executions have no return value which you could capture in

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

This only works for methods. So please use

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

instead if you do need the constructed object for any purpose.




回答2:


Here is the working solution from kriegaex in its entirety:

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;
  }
}



回答3:


THE FOLLOWING WORKS, BUT IS NOT RECOMMENDED BY kriegaex. PROVIDED HERE AS POSSIBLE MATERIAL THAT COULD BE REPURPOSED IF THE NEED ARISES.

This was my first working solution to the problem which uses in part the initialization() pointcut primitive.

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;
  }
}


来源:https://stackoverflow.com/questions/12184391/how-to-define-an-aspectj-pointcut-that-picks-out-all-constructors-of-a-class-tha

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!