我们如何使用@RabbitListener

时间:2015-12-29 15:03:37

标签: spring-amqp spring-rabbit

问题:我正在从MessageListener接口impl迁移到@RabbitListener。我有这样的逻辑,我在一个由几个类继承的MessageListener上做“pre”和“post”消息处理

示例:

public AbstractMessageListener implements MessageListener {

     @Override
     public void onMessage(Message message) {

          //do some pre message processing

          process(Message message);

          // do some post message processing
     }

     protected abstract void process(Message message);

}

问题:有没有办法可以使用@RabbitListener注释实现类似的功能我可以继承前/后消息处理逻辑,而无需重新实现或调用内部的前/后消息处理每个子项@RabbitListener注释,同时为子项@RabbitListener维护一个可自定义的方法签名?或者这太贪心了?

示例所需结果:

public class SomeRabbitListenerClass {

    @RabbitListener( id = "listener.mypojo",queues = "${rabbitmq.some.queue}")
   public void listen(@Valid MyPojo myPojo) {
      //...
   }
}

public class SomeOtherRabbitListenerClass {

    @RabbitListener(id = "listener.orders",queues ="${rabbitmq.some.other.queue}")
   public void listen(Order order, @Header("order_type") String orderType) {
      //...
   }
}

这两个@RabbitListener使用相同的继承前/后消息处理

我看到@RabbitListener注释中有一个'containerFactory'参数,但我已经在配置中声明了一个......我真的很确定如何用自定义的containerFactory实现我想要的继承。

更新答案:这就是我最终要做的事情。

建议定义:

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.amqp.core.Message;

/**
 * AOP Around advice wrapper. Every time a message comes in we can do 
 * pre/post processing by using this advice by implementing the before/after methods.
 * @author sjacobs
 *
 */
public class RabbitListenerAroundAdvice implements MethodInterceptor {

    /**
     * place the "AroundAdvice" around each new message being processed.
     */
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {

        Message message = (Message) invocation.getArguments()[1];

        before(message)
        Object result = invocation.proceed();
        after(message);

        return  result;
    }

声明bean:在你的rabbitmq配置中,将建议声明为Spring bean并将其传递给rabbitListenerContainerFactory#setAdviceChain(...)

//...

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory() {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory( cachingConnectionFactory() );
        factory.setTaskExecutor(threadPoolTaskExecutor());
        factory.setMessageConverter(jackson2JsonMessageConverter());   

        factory.setAdviceChain(rabbitListenerAroundAdvice());

        return factory;
    }

    @Bean
    public RabbitListenerAroundAdvice rabbitListenerAroundAdvice() {
        return new RabbitListenerAroundAdvice();
    }

// ...

2 个答案:

答案 0 :(得分:4)

<强>校正

您可以使用SimpleRabbitListenerContainerFactory中的建议链将周围建议应用于为@RabbitListener创建的侦听器;这两个参数是ChannelMessage

如果您只需要在调用侦听器之前执行操作,则可以将MessagePostProcessor(s)添加到容器afterReceivePostProcessors

答案 1 :(得分:0)

这里的继承是不可能的,因为对POJO方法和MessageListener实现的注释处理是完全不同的故事。

使用MessageListener,您可以完全控制目标行为和container

使用注释只处理POJO,无框架代码。特定MessageListener在后​​台创建。而那个完全基于带注释的方法。

我说我们可以使用Spring AOP Framework来实现您的需求。

请参阅最近的问题及其在此问题上的答案:How to write an integration test for @RabbitListener annotation?