Héctor
Héctor

Reputation: 26054

@AspectJ: Pointcut for any method of custom annotated class

I'm trying to detect in a pointcut any method of a class annotated with my annotation @NFCDisable.

@NFCDisable
public class MyClass { 
    //methods
}

I have tried this:

@Aspect
public class NFCAspect {

    @Before("method()")
    public void exec() {
        //DO SOMETHING
    }

    @Pointcut("@within(NFCDisable) || @annotation(NFCDisable)")
    public void method() {}
}

But it doesn't work. What am I doing wrong?

Thanks.

Upvotes: 0

Views: 1932

Answers (1)

kriegaex
kriegaex

Reputation: 67317

It works as long as your aspect and annotation are in the same package. Otherwise the aspect should cause compiler errors such as:

Type referred to is not an annotation type: @missing@

But even if they are in the same package, the pointcut catches way too many joinpoints such as:

staticinitialization(de.scrum_master.app.MyClass.<clinit>)
preinitialization(de.scrum_master.app.MyClass())
initialization(de.scrum_master.app.MyClass())
execution(de.scrum_master.app.MyClass())
execution(void de.scrum_master.app.MyClass.foo())
execution(int de.scrum_master.app.MyClass.bar(String))

This includes static class initialisation, constructor execution and constructor (pre-)initialisation in addition to the method executions you want to see.

So what do you need to do?

  • Restrict the pointcut to really only target method executions.
  • Use fully qualified class names in annotation-based AspectJ syntax.
  • Make sure your annotation has runtime retention scope.

Here is a full example:

package de.scrum_master.app;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface NFCDisable {}
package de.scrum_master.app;

@NFCDisable
public class MyClass {
    public void foo() {}
    public int bar(String text) { return 11; }
}
package de.scrum_master.app;

public class Application {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.foo();
        myClass.bar("xxx");
    }
}
package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class NFCAspect {
    @Pointcut("execution (* *(..)) && @within(de.scrum_master.app.NFCDisable)")
    public void method() {}

    @Before("method()")
    public void exec(JoinPoint thisJoinPoint) {
        System.out.println(thisJoinPoint);
    }
}

Console output:

execution(void de.scrum_master.app.MyClass.foo())
execution(int de.scrum_master.app.MyClass.bar(String))

P.S.: The pointcut could also be written like this, which is a bit harder to read IMO:

@Pointcut("execution (* (@de.scrum_master.app.NFCDisable *).*(..))")

Upvotes: 3

Related Questions