如何在销毁Web应用程序中的所有其他bean之前关闭Spring任务执行程序/调度程序池? [英] How can I shutdown Spring task executor/scheduler pools before all other beans in the web app are destroyed?

查看:117
本文介绍了如何在销毁Web应用程序中的所有其他bean之前关闭Spring任务执行程序/调度程序池?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Spring Web应用程序中,我有几个DAO和服务层bean。一个服务层bean具有带注释的@Async / @Scheduled方法。这些方法依赖于其他(自动装配的)bean。
我已经用XML配置了两个线程池:

In a Spring web application I have several DAO and service layer beans. One service layer bean has annotated @Async / @Scheduled methods. These methods depend on other (autowired) beans. I have configured two thread pools in XML:

<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
     <property name="corePoolSize" value="2" />
     <property name="maxPoolSize" value="5" />
     <property name="queueCapacity" value="5" />
     <property name="waitForTasksToCompleteOnShutdown" value="true" />
     <property name="rejectedExecutionHandler">
            <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/>
        </property>
    </bean>

<bean id="taskScheduler" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
     <property name="poolSize" value="10" />
     <property name="waitForTasksToCompleteOnShutdown" value="true" />
     <property name="rejectedExecutionHandler">
            <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/>
        </property>
    </bean>

    <task:annotation-driven executor="taskExecutor" scheduler="taskScheduler"/>

一切都按预期工作。我的问题是我无法完全关闭任务池。任务在数据库和文件系统上运行。当我停止Web应用程序时,它需要一些时间才能停止。这表示 waitForTasksToCompleteOnShutdown 属性有效。但是,我在日志中得到了IllegalStateExceptions,表明某些bean已经被销毁,但是一些工作任务线程仍在执行,并且它们因为依赖项被破坏而失败。

Everything works as expected. My problem is that I cannot get a clean shutdown of the task pools to work. The tasks operate on the database and on the file system. When I stop the web application it takes some time until it is stopped. This indicates that the waitForTasksToCompleteOnShutdown property works. However, I get IllegalStateExceptions in the log indicating that some beans are already destroyed but some worker task threads are still executing and they fail because their dependencies are destroyed.

有一个可能相关的JIRA问题: SPR-5387

There is a JIRA issue which might be relevant: SPR-5387

我的问题是:有没有办法告诉Spring最后初始化任务执行程序/调度程序bean,还是有办法告诉Spring先破坏它们? / strong>

My question is: Is there a way to tell Spring to initialize the task executor/scheduler beans last or is there a way to tell Spring to destroy them first?

我的理解是销毁发生在颠倒的初始化顺序中。因此,最后初始化的bean将首先被销毁。如果首先销毁线程池bean,那么所有当前正在执行的任务都将完成,并且仍然可以访问依赖bean。

My understanding is that destruction takes place in reversed init order. Therefore the bean init'ed last will be destroyed first. If the thread pool beans are destroyed first, all currently executing tasks would finish and could still access dependent beans.

我也尝试在线程上使用depends-on属性引用我的服务bean的池,它有@Async和@Scheduled注释。好像它们从未执行过,我没有得到上下文初始化错误。我假设带注释的服务bean在某种程度上需要首先初始化这些线程池,如果我使用依赖,我会颠倒顺序并使它们不起作用。

I have also tried using the depends-on attribute on the thread pools referring to my service bean which has the @Async and @Scheduled annotations. Seems like they are never executed then and I do not get context initialization errors. I assume the annotated service bean somehow needs these thread pools initialized first and if I use depends-on I reverse the order and make them non-functional.

推荐答案

两种方式:


  1. 有一个bean工具 ApplicationListener< ContextClosedEvent> onApplicationEvent()将在上下文和所有bean被销毁之前被调用。

  1. Have a bean implement ApplicationListener<ContextClosedEvent>. onApplicationEvent() will get called before the context and all the beans are destroyed.

有一个bean实施生命周期 SmartLifecycle stop()将在上下文和所有bean被销毁之前被调用。

Have a bean implement Lifecycle or SmartLifecycle. stop() will get called before the context and all the beans are destroyed.

无论哪种方式,都可以在bean销毁机制发生之前关闭任务。

Either way you can shut down the task stuff before the bean destroying mechanism takes place.

例如:

@Component
public class ContextClosedHandler implements ApplicationListener<ContextClosedEvent> {
    @Autowired ThreadPoolTaskExecutor executor;
    @Autowired ThreadPoolTaskScheduler scheduler;

    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        scheduler.shutdown();
        executor.shutdown();
    }       
}

(编辑:固定方法签名)

( Fixed method signature)

这篇关于如何在销毁Web应用程序中的所有其他bean之前关闭Spring任务执行程序/调度程序池?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆