我遇到了Spring Boot(1.5.6)应用程序的问题,我希望在关机时执行一些清理工作。 My Boot应用程序打包为war
,并部署在Wildfly 10应用程序容器中。
我尝试了以下内容:
@Component
public class Cleanup {
private static final Logger log = LoggerFactory.getLogger(Cleanup.class);
@Autowired
@Qualifier("rabbitConnection")
private Connection rmqConnection;
@PreDestroy
public void shutdownConnection() throws JMSException{
System.out.println("************************SHUTTING DOWN************************");
rmqConnection.close();
}
@PostConstruct
public void postConstruct(){
log.warn("POST CONSTRUCT");
}
}
我看到Spring注册了钩子:
2017-09-05 12:14:15,146 DEBUG [org.springframework.context.annotation.CommonAnnotationBeanPostProcessor] Registered init method on class [org.jms.Cleanup]: org.springframework.beans.factory
.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement@a1ab9f17
2017-09-05 12:14:15,146 DEBUG [org.springframework.context.annotation.CommonAnnotationBeanPostProcessor] Registered destroy method on class [org.jms.Cleanup]: org.springframework.beans.fact ory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement@5d82edd4
我也在日志文件中看到“POST CONSTRUCT”,但是从未调用@PreDestroy
方法,即使我已经在Wildfly中禁用/取消部署该应用程序。
然后我想我会尝试添加一个ApplicationListener,但是我不确定当应用程序由org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener
而不是main()
方法引导时如何做到这一点。
我意识到我可以使用ContextListener,但这使我的目的失败了一点,使其成为一般风格的应用程序。我希望分配一个ApplicationListener,但是由于我无法控制SpringApplication的创建(发生在SpringBootContextLoaderListener
,但是没有用。
我的最后一次尝试是创建一个@EventListener
,但也未能解雇:
@Component
public class Cleanup {
private static final Logger log = LoggerFactory.getLogger(Cleanup.class);
@Autowired
@Qualifier("rabbitConnection")
private Connection rmqConnection;
@EventListener
public void handleContextRefresh(ContextStoppedEvent event) {
System.out.println("************************STOPPING CONTEXXT************************");
log.warn("STOPPING CONTEXT");
try {
rmqConnection.close();
} catch (JMSException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
日志显示已注册:
2017-09-05 12:28:49,678 DEBUG [org.springframework.context.event.EventListenerMethodProcessor] 1 @EventListener methods processed on bean 'cleanup': {public void org.jms.Cleanup.handleConte xtRefresh(org.springframework.context.event.ContextStoppedEvent)=@org.springframework.context.event.EventListener(value=[], classes=[], condition=)}
日志还显示正在关闭上下文:
2017-09-05 12:39:42,723 INFO [org.wildfly.extension.undertow] WFLYUT0021: Registered web context: /jms-0.0.1-SNAPSHOT
2017-09-05 12:39:43,335 INFO [org.jboss.as.server] WFLYSRV0010: Deployed "jms-0.0.1-SNAPSHOT.war" (runtime-name : "jms-0.0.1-SNAPSHOT.war")
2017-09-05 12:41:22,771 INFO [org.wildfly.extension.undertow] WFLYUT0022: Unregistered web context: /jms-0.0.1-SNAPSHOT
2017-09-05 12:41:22,776 INFO [io.undertow.servlet] Closing Spring root WebApplicationContext
2017-09-05 12:41:23,314 INFO [org.jboss.as.server.deployment] WFLYSRV0028: Stopped deployment jms-0.0.1-SNAPSHOT.war (runtime-name: jms-0.0.1-SN
APSHOT.war) in 545ms
2017-09-05 12:41:23,532 INFO [org.jboss.as.server.deployment.scanner] WFLYDS0018: Deployment jms-0.0.1-SNAPSHOT.war was previously deployed by t
his scanner but has been undeployed by another management tool. Marker file C:\dev\tmp\jboss-eap-7.0.0\standalone\deployments\jms-0.0.1-SNAPSHOT.war.
undeployed is being added to record this fact.
2017-09-05 12:41:23,544 INFO [org.jboss.as.server] WFLYSRV0009: Undeployed "jms-0.0.1-SNAPSHOT.war" (runtime-name: "jms-0.0.1-SNAPSHOT.war")
我的Java Config类:
@SpringBootApplication
@EnableJms
public class JmsReceiver {
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
factory.setDestinationResolver(new BeanFactoryDestinationResolver(springContextBeanFactory));
factory.setConcurrency("1");
factory.setAutoStartup(true);
factory.setPubSubDomain(false);
return factory;
}
@Bean
public ConnectionFactory connectionFactory() {
RMQConnectionFactory conn = new RMQConnectionFactory();
conn.setUsername("test");
conn.setPassword("test");
conn.setHost("localhost");
conn.setPort(5672);
conn.setVirtualHost("test");
conn.setOnMessageTimeoutMs(2000);
return conn;
}
}
我现在有点不知所措,我还可以尝试注册一个关机钩子。我甚至尝试过实施DisposableBean
,但无济于事。
此时推荐的机制是什么?这是一个容器问题吗?如何在Spring Boot webapp中添加关机监听器?如果我使用旧版org.springframework.boot.legacy.context.web.SpringBootContextLoaderListener
?
我创建了一个示例应用程序来显示https://github.com/benze/springbootevents处事件的问题。