Search code examples
javaoverridingaopaspectjpointcut

AspectJ - can't override pointcut - parameter types don't match


I have an abstract aspect like this:

public abstract aspect GenericAspect<T> {

    public abstract T createT(Object[] args);

    abstract pointcut callMethod(Object[] args);

    T around(Object[] args) : callMethod(args) {
        return createT(args);
    }
}

And I would like to extend this aspect to another one abstract aspect that overrides only the abstract pointcut. Like the following example (where Foo is an interface):

public abstract aspect FooAspect extends GenericAspect<Foo> {

    pointcut callMethod(Object[] args):
        call(Foo *.*(..)) && args(args);
}

But I have this compile error:

can't override pointcut GenericAspect.callMethod(java.lang.Object[]) with pointcut FooAspect.callMethod(java.lang.Object[]) parameter don't match

How can I solve this issue?


Solution

  • I do not know exactly why your example does not work, maybe there is a little bug in AspectJ or you have just made false assumptions concerning what is possible with AspectJ in combination with generics and abstract pointcuts. I suggest you ask the same question on the AspectJ users mailing list.

    In the meantime, would it be okay for you to do this, slightly modifying the syntax and moving the args() binding into the advice rather than into the pointcut?

    Driver application:

    package de.scrum_master.app;
    
    public class Application {
      public static void main(String[] args) {
        System.out.println(new Application().createFoo());
      }
    
      public Foo createFoo(Object... args) {
        return null;
      }
    }
    

    Helper class:

    package de.scrum_master.app;
    
    public class Foo {}
    

    Aspects:

    package de.scrum_master.aspect;
    
    public abstract aspect GenericAspect<T> {
      public abstract T createT(Object[] args);
    
      abstract pointcut callMethod();
    
      T around(Object[] args): callMethod() && args(args) {
        return createT(args);
      }
    }
    
    package de.scrum_master.aspect;
    
    import de.scrum_master.app.Foo;
    
    public abstract aspect FooAspect extends GenericAspect<Foo> {
      pointcut callMethod():
        call(Foo *(..));
    }
    
    package de.scrum_master.aspect;
    
    import de.scrum_master.app.Foo;
    
    public aspect ConcreteFooAspect extends FooAspect {
      @Override
      public Foo createT(Object[] args) {
        return new Foo();
      }
    }
    

    Console log:

    de.scrum_master.app.Foo@511d50c0
    

    Please note that the aspect kicks in, otherwise null would be printed here.