Spring AMQP 侦听器在 autoStartup = false 时启动
Spring AMQP Listener starts when autoStartup = false
最近遇到 Spring AMQP @EventListener
的奇怪问题。
Listener 是这样声明的,所以 autostartup 被设置为 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 按预期工作,并没有按预期在启动时启动侦听器。
- 在我的例子中,
context.refresh()
和 context.start()
是从内部平台的代码手动调用的问题。在那种情况下,RabbitListenerEndpointRegistry
中的 contextRefreshed
标志被设置为真,并且在第二次调用 startIfNecessary
期间(因为 context.start()
)监听器被启动。
最近遇到 Spring AMQP @EventListener
的奇怪问题。
Listener 是这样声明的,所以 autostartup 被设置为 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 按预期工作,并没有按预期在启动时启动侦听器。
- 在我的例子中,
context.refresh()
和context.start()
是从内部平台的代码手动调用的问题。在那种情况下,RabbitListenerEndpointRegistry
中的contextRefreshed
标志被设置为真,并且在第二次调用startIfNecessary
期间(因为context.start()
)监听器被启动。