Pointcut confusion with inheritance

2.5k views Asked by At

I am confused by writing a pointcut that matches all executions of a method. I tried the pointcut that should match all method-executions of class Alpha:

execution(* Alpha.*(..))

with the following class-hierachy

public class Alpha {
    public void alphaMethod() {...}
}
public class Beta extends Alpha {
    public void betaMethod() {
        alphaMethod();
    }
}

If the Main-program calls alphaMethod on an Beta-instance my advice is called like expected but the Main-program calls betaMethod that also calls alphaMethod inside my advice is not called and I don't understand why.

Aspect-Definition:

@Aspect
public class MyAspect {
    @Before(value = "execution(* Alpha.*(..))", argNames="joinPoint")
    public void myAdvice(JoinPoint joinPoint) {
        System.out.println("BEFORE: " + joinPoint.getSignature());
    }
}

Main-method:

Beta beta = ...;
beta.alphaMethod(); //advice is called
beta.betaMethod(); //advice is NOT called.
2

There are 2 answers

2
darrengorman On BEST ANSWER

This is expected.

Spring AOP uses proxy classes to wrap advised beans. When you call alphaMethod() from within a Beta method, the proxy isn't even aware of it.

See this answer for more information.

1
Marko Topolnik On

The reason, as already answered, is clear. You can fix this by employing load-time weaving instead of proxying (I guess it comes down to a config option somewhere and a dependency to AspectJ, if not already depending on it) or injecting the bean to itself as a dependency and then implementing

public void betaMethod() {
    selfBean.alphaMethod();
}

This will work because selfBean is not the same reference as this, the former being a reference to the proxy, the latter a reference to the original, proxied object.