我创造了一个简单的" Hello World"样式应用程序测试spring-amqp和RabbitMQ。使用ClassPathXmlApplicationContext
从main函数加载Spring上下文,它启动amqp并设置一个ListenerContainer,用于侦听队列上的消息并在指定的pojo上调用指定的方法。一切正常,除了关闭应用程序。我在spring上下文中尝试了close()
方法,它启动了ListenerContainer的关闭,它关闭了工作线程但是应用程序挂起而且它没有退出。我还在上下文中尝试了stop()
,在ListenerContainer bean上尝试了shutdown()
。
问题: 如何干净地关闭具有spring-amqp ListenerContainers的spring上下文?
关机期间此处的日志输出:
Jul 07, 2014 1:00:22 AM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@472a2a50: startup date [Mon Jul 07 01:00:08 CEST 2014]; root of context hierarchy
Jul 07, 2014 1:00:22 AM org.springframework.context.support.DefaultLifecycleProcessor stop
INFO: Stopping beans in phase 2147483647
Jul 07, 2014 1:00:22 AM org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer doShutdown
INFO: Waiting for workers to finish.
Jul 07, 2014 1:00:23 AM org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer doShutdown
INFO: Successfully waited for workers to finish.
应用程序挂起并且在此输出后不会退出。
这是主要方法:
public static void main(String[] args) {
final ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:app-config.xml");
ctx.registerShutdownHook();
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("Quitting from Main...");
ctx.close();
}
}, 10000);
}
这是app-config.xml
<beans ...>
<context:annotation-config />
<import resource="amqp-config.xml" />
<bean id="messageReceiver" class="com.knesek.amqp.spring.MessageReceiver" />
</beans>
与spring-amqp相关的配置(amqp-config.xml):
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns="http://www.springframework.org/schema/rabbit" ...>
<connection-factory id="connectionFactory" username="guest" password="guest" host="127.0.0.1"/>
<template id="amqpTemplate" connection-factory="connectionFactory"/>
<admin connection-factory="connectionFactory" />
<direct-exchange name="incomingMessages">
<bindings>
<binding key="messages.inbound" queue="inboundMsgs"/>
</bindings>
</direct-exchange>
<listener-container id="listenerContainer" connection-factory="connectionFactory" >
<listener ref="messageReceiver" method="receiveMessage" queues="inboundMsgs" />
</listener-container>
<queue name="inboundMsgs"/>
</beans:beans>
答案 0 :(得分:2)
听起来你有一些非守护程序线程可以保持你的上下文活着。关闭上下文应该停止任何框架线程。我建议你使用jstack / visualvm进行线程转储。