在Wildfly容器中部署的SpringBoot WAR应用程序中未调用@PreDestroy

时间:2017-09-05 16:37:48

标签: java spring spring-boot

我遇到了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处事件的问题。

0 个答案:

没有答案