Search code examples
springamazon-sqsaopspring-aopspring-messaging

Spring AOP pointcut execution not working


I'm working on a Spring Boot project that uses Spring Cloud (io.awspring.cloud:spring-cloud-aws-dependencies:2.4.2) to produce and consume AWS SQS messages. I have several message producers and several message consumers, and all is working fine from that perspective.

I now have a cross cutting concern where I need to set a header on all messages being produced/sent; and to read that header on all messages being consumed (correlationId), and AOP seems like a good fit.

My aspect for handling (receiving) a message works fine:

    @Before("execution(* org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler.handleMessage(..))")
    fun beforeHandleMessage(joinPoint: JoinPoint) {

The class and method that it is targeting is:

package org.springframework.messaging.handler.invocation;
...
public abstract class AbstractMethodMessageHandler<T>
        implements MessageHandler, ApplicationContextAware, InitializingBean {
...
    @Override
    public void handleMessage(Message<?> message) throws MessagingException {

As mentioned, this works great.

However, I can't get my pointcut for sending a message working. This is my aspect:

    @Before("execution(* org.springframework.messaging.support.AbstractMessageChannel.send(..))")
    // @Before("execution(* io.awspring.cloud.messaging.core.QueueMessageChannel.send(..))")
    fun beforeSendMessage(joinPoint: JoinPoint) {

And the class and method that I'm trying to target is this:

package org.springframework.messaging.support;
...
public abstract class AbstractMessageChannel implements MessageChannel, InterceptableChannel, BeanNameAware {
...
    @Override
    public final boolean send(Message<?> message) {

But it doesn't seem to work. I've also tried writing the pointcut to target the concrete implementation class (as commented out above), but that also does nothing.

I can't see what the difference is between my working pointcut for beforeHandleMessage and beforeSendMethod, other than the pointcut for beforeSendMethod is targeting a final method. Is that relevant?

Any pointers to get this working would be very much appreciated;
Thanks


Solution

  • I found the answer from this other SO answer: Spring AOP ignores some methods of Hessian Service

    I know that Spring AOP won't intercept local method calls. I.e. the proxy which is applied doesn't intercept the calls if the same object calls its own method, even if it matches the pointcut expression.

    The problem was that the send method I was targeting was called by a number of other methods in the class.

    Looking at the call stack I found a different method that was the first method called in the class. Changing the pointcut to target that method has worked.