Search code examples
springspring-amqpspring-rabbit

Spring rabbit: Intercept method calls annotated with @RabbitListener without AspectJ usage


Is there a way to intercept calls of bean methods annotated with @RabbitListener without using AspectJ.

The code is something like this

@OtherAnnotation
@RabbitListener
public void do(Message message)

I need to intercept all calls to @RabbitListener method, if the method has @OtherAnnotation annotation.

UPDATE:

I managed to make it work using Gary Russell solution.

public class CustomRabbitListenerAnnotationBeanPostProcessor extends RabbitListenerAnnotationBeanPostProcessor {

    @Override
    protected void processAmqpListener(RabbitListener rabbitListener, final Method method, Object bean, String beanName) {
        if (method.isAnnotationPresent(OtherAnnotation.class)) {
            ProxyFactory proxyFactory = new ProxyFactory(bean);
            proxyFactory.addAdvisor(new StaticMethodMatcherPointcutAdvisor(new OtherAnnotationInterceptor()) {
               @Override
               public boolean matches(Method advisorMethod, Class<?> targetClass) {
                  return advisorMethod.equals(method);
               }
            });
            Object proxiedBean = proxyFactory.getProxy();
            super.processAmqpListener(rabbitListener, method, proxiedBean, beanName);
        } else {
            super.processAmqpListener(rabbitListener, method, bean, beanName);
        }
    }
}

The bean definition is like:

    @Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
    public CustomRabbitListenerAnnotationBeanPostProcessor customRabbitListenerAnnotationBeanPostProcessor() {
        return new CustomRabbitListenerAnnotationBeanPostProcessor();
    }

It's a bit ugly, but it works. If anyone has better solution, please share it.


Solution

  • You can subclass RabbitListenerAnnotationBeanPostProcessor and override the processListener method and modify the bean before invoking the super version.

    Then, replace the RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME bean registered by the @EnableRabbit with your subclass.

    Or, simply add your advice to the container factory's advice chain and all listeners will be advised. You can then do a runtime check to see if the other annotation is present.