首页 > 解决方案 > 当 autoStartup = false 时 Spring AMQP Listener 启动

问题描述

最近遇到了 Spring AMQP 的一个奇怪问题@EventListener。监听器是这样声明的,所以自动启动设置为false

@RabbitListener(id = "MqMessageHandler", queues = "${rabbitMQ.in-queue-name}", autoStartup = "false")
public void receiveMessage(Message message) {

在应用程序完全初始化并且我从其他一些服务获得响应后,我正在像这样手动启动侦听器

MessageListenerContainer mqMessageHandler = registry.getListenerContainer(HANDLER_ID);
mqMessageHandler.start();

但似乎侦听器仍在启动上下文初始化。在代码中挖掘了一下,我在里面找到了这段代码RabbitListenerEndpointRegistry

    /**
     * Start the specified {@link MessageListenerContainer} if it should be started
     * on startup or when start is called explicitly after startup.
     * @param listenerContainer the container.
     * @see MessageListenerContainer#isAutoStartup()
     */
    private void startIfNecessary(MessageListenerContainer listenerContainer) {
        if (this.contextRefreshed || listenerContainer.isAutoStartup()) {
            listenerContainer.start();
        }
    }

这意味着一旦ContextRefreshed事件被触发,监听器就会被启动。我希望条件是 this.contextRefreshed && listenerContainer.isAutoStartup() 这样,&&而不是||然后它应该按预期工作。

有谁知道条件是否正确,我的假设是否错误?Spring AMQP 版本2.3.1与我在2.3.10

作为现在的解决方法,我正在像这样手动注册侦听器

        MessageListenerContainer mqMessageHandler = registry.getListenerContainer(HANDLER_ID);
        if (Objects.isNull(mqMessageHandler)) {
            SimpleRabbitListenerEndpoint endpoint = new SimpleRabbitListenerEndpoint();
            endpoint.setQueueNames(inQueueName);
            endpoint.setMessageListener(this.mqMessageHandler);
            endpoint.setId(HANDLER_ID);

            registry.registerListenerContainer(endpoint, factory);
            mqMessageHandler = registry.getListenerContainer(HANDLER_ID);
        }
        mqMessageHandler.start();

标签: spring-amqp

解决方案


所以经过调查发现:

  1. Spring AMQP 按预期工作,并没有按预期在启动时启动侦听器。
  2. 就我而言,这是一个问题,它是context.refresh()context.start()内部平台的代码中手动调用的。在这种情况下,contextRefreshed标志 inRabbitListenerEndpointRegistry设置为 true,并且在第二次调用startIfNecessary(因为context.start())监听器期间启动。

推荐阅读