Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointcuts on inherited methods (in a class design-agnostic context)

I am fiddling around with AspectJ and came up with an idea that I don't seem to be able to implement properly (story of my life).

I have defined an aspect :

package my.package;

import org.aspectj.lang.annotation.*;
import org.aspectj.lang.ProceedingJoinPoint;

@Aspect
public class MyAspect {

    @Pointcut("execution(* *(..)) && this(o)")
    public void instanceMethod(Object o) {}

    @Pointcut("within(@Marker *)")
    public void methodsFromMarkedClasses() {}

    @Around("methodsFromMarkedClasses() && instanceMethod(o)")
    public Object markedMethodsAdvice(ProceedingJoinPoint joinPoint, Object o) throws Throwable {
        // do awesome stuff
        return null; //<- not the actual return, just added this so that my head wouldn't hurt
    }
}

I have defined @Marker annotation which is just empty.

The idea is to have the advice markedMethodsAdvice execute ANY time a method is called on an object of a class marked with @Marker. Even (and here're the tricky parts) :


Case 1

If said method is inherited from a class that is not marked see example :

Given

package my.package;
public class Alpha {
    public void methodA() {}
}

When

package my.package;
@Marked
public class Beta extends Alpha {}

Then

/* Should trigger the advice */
new Beta().methodA();

Case 2

If said method is called on an object of a subclass (Liskov)

Given

@Marked
public class Beta extends Alpha { //still extends A just to be coherent with previous example
    public void methodB() {}
}

When

package my.package;
public class Gamma extends Beta {
}

Then

/* Should trigger the advice */
new Gamma().methodB();

(And since I'm greedy I ask this bonus one)

Case 3

If said method is declared on a subclass

Given

@Marked
public class Beta extends Alpha {} //still extends A just to be coherent with previous example

When

package my.package;
public class Gamma extends Beta {
    public void methodC() {}
}

Then

/* Should trigger the advice */
new Gamma().methodC();

The aspectj documentation seems to state that this is possible

execution(public void Middle.*())

picks out all method executions for public methods returning void and having no arguments that are either declared in, or inherited by, Middle, even if those methods are overridden in a subclass of Middle

So what did I do wrong ?

like image 306
Ar3s Avatar asked Jun 04 '15 16:06

Ar3s


1 Answers

You could try to annotate @Marker annotation with @Inherited annotation. Subclasses should inherit @Marker annotation.

java.lang.annotation.Inherited

@Inherited
public @interface Marked{

}
like image 59
jlvaquero Avatar answered Sep 30 '22 05:09

jlvaquero