10
votes

I am getting started with AOP for the first time.

I have my first aspect as follows:

@Aspect
public class SyncLoggingAspect {
    private final Logger logger = Logger.getLogger(this.getClass());

    @Before("execution(public * *(..))")
    public void anyPublic() {
        System.out.println("HIT POINTCUT");
    }
}

This sucessfully proceeds to be invoked on any method call which is public. However when I change it to this:

@Before("execution(public * doPoll(..))")
public void anyPublic() {
    System.out.println("HIT POINTCUT");
}

I would expect it to work on any public method called "doPoll", yet when a method such as this is called nothing happens:

public class GmailContactPoller extends ContactPoller<GoogleUser, ContactPusher<GoogleUser>> {
    Logger logger = Logger.getLogger(this.getClass());

    @Override
    public List<? extends ContactPusher<GoogleUser>> doPoll() throws PollException {
           ...
    }
}

Is there something I am missing with the EL syntax? Or is this something to do with the inheritance hierarchy? The superclass method of doPoll is abstract in an abstract class called Poller. Does not having an interface cause problems?

Edit: I just noticed my IDE enables spring aspect tooling, and now I have the following compiler warning by the method:

"Description Resource Path Location Type advice defined in datasync.aop.aspects.SyncLoggingAspect has not been applied [Xlint:adviceDidNotMatch] SyncLoggingAspect.java /DataSync/src/main/datasync/aop/aspects"

2
Unrelated to the syntax, do you use Spring AOP proxies? If this is the case I guess you created GmailContactPoller as a Spring bean, not a using new. Do you call doPoll from the same object? In this case Spring proxies are not working since you are calling this.doPoll instead of proxifiedInstance.doPoll - gabuzo
My GmailContactPoller is created as a spring bean. From outside of this bean a public method is called, which in turn calls it's own abstract method doPoll() (doPoll is actually protected but for this example I left it as public so the difference between the working and not working expression is one word). So you are correct that it follows the path proxy.this.method1 > call > this.doPoll. I was not aware this was the behaviour as I thought aspect J worked in a different way by manipulating byte code or weaving at compile time? Or is spring AOP seperate in it's implementation? - mogronalol
With further fiddling you are correct, is there a solution to get around this? - mogronalol

2 Answers

5
votes

Spring AOP Proxies and aspectJ had some differences mainly:

  • Spring AOP only works on public methods.
  • Spring AOP does not work for self invocations.

You can have a look to sections 8.4 & 8.5 of Spring's Documentation for more information.

Currently you have two solutions:

  1. refactor your code to remove the need for self invocation
  2. use AspectJ rather than Spring AOP proxies either at compile time or load time.
2
votes

Try:

@Before("execution(public * *.doPoll(..))")
public void anyPublic() {
    System.out.println("HIT POINTCUT");
}