将Spring任务XML配置转换为代码配置

时间:2015-05-13 14:25:03

标签: java spring configuration scheduled-tasks task

我正在尝试将使用Spring的任务框架的XML配置转换为纯粹的代码配置。我能够重现这些功能,但每当我关闭Tomcat服务器上的任务调度程序的战争时,它就会挂起(它不会挂起XML配置)。我已经调试过来检查调度程序和执行程序的实例,但是我没有看到差异所以我不确定是什么导致它挂起。

以下是适用的XML配置:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
   http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd">

   <task:executor id="com.work.gwx.pix.executor"
      pool-size="${pix.job.executor.pool.size:1-40}"
      queue-capacity="${pix.job.executor.queue.capacity:0}"
      rejection-policy="CALLER_RUNS"/>

   <task:scheduler id="com.work.gwx.pix.scheduler" pool-size="${pix.job.scheduler.pool.size:4}"  />

    <task:annotation-driven executor="com.work.gwx.pix.executor" scheduler="com.work.gwx.pix.scheduler" />

    <bean id='queueProcessor' class="com.work.gwx.queueing.QueueProcessor" /> 

 </beans>

以下是代码配置:

@EnableAsync
@EnableScheduling
@Configuration
public class TaskConfiguration implements AsyncConfigurer, SchedulingConfigurer {

    @Value("${pix.job.executor.max.pool.size:1}")
    private int executorMaxPoolSize;

    @Value("${pix.job.executor.queue.capacity:0}")
    private int executorQueueCapacity;

    @Value("${pix.job.scheduler.pool.size:4}")
    private int schedulerPoolSize;

    @Bean(destroyMethod = "shutdown")
    public Executor pixTaskScheduler() {
        final ScheduledThreadPoolExecutor ex = new ScheduledThreadPoolExecutor(schedulerPoolSize, new ThreadPoolTaskExecutor());
        // ex.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
        return ex;
    }

    @Bean
    public Executor pixExecutor() {
        final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(executorMaxPoolSize);
        executor.setQueueCapacity(executorQueueCapacity);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.setThreadFactory(new ThreadPoolTaskExecutor());
        executor.initialize();
        return executor;
    }

    @Override
    public void configureTasks(final ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(pixTaskScheduler());

    }

    @Override
    public Executor getAsyncExecutor() {
        return pixExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

当我在代码配置中使用setExecuteExistingDelayedTasksAfterShutdownPolicy(false)时,它会关闭,但我担心可能会产生不利影响,因为在通过XML配置完成时会设置为true。另外,我应该注意,QueueProcessor类正在进行我想要的工作,我不介意延迟执行是否被取消 - 我只是不希望当前正在执行的线程被突然取消。

这是我挂起时收到的消息:

  

严重:Web应用程序[/ pix-queue-processor]似乎有   启动了一个名为[ThreadPoolTask​​Executor-1]的线程,但未能成功   停下来。这很可能会造成内存泄漏。

关于可能导致悬挂的任何想法?或者,使用这个注释掉的方法让我做我想做的事情(不会杀死正在运行的任务但会取消延迟的任务)?

1 个答案:

答案 0 :(得分:5)

您的基于Java的配置实际上并不代表XML配置。至少有两件事是不同的。

  1. 您的TaskExecutor还有另一个TaskExecutor有线ThreadFactory,这不是XML中的情况,也是另一个TaskExecutor
  2. 您的TaskScheduler使用新的TaskExecutor,而xml配置使用已配置的。{/ li>

    让您的任务在关闭时完成,您可以将waitForTasksToCompleteOnShutdown上的TaskExecutor属性设置为true,然后任何待处理任务都将完成,并且不会接受任何新任务。

    此外,不应调用initialize,因为afterPropertiesSet方法将由Spring调用,而initialize方法将调用TaskExecutor

    以下2个bean定义更符合XML配置(现在您只有一个@Bean(destroyMethod = "shutdown") public Executor pixTaskScheduler() { final ScheduledThreadPoolExecutor ex = new ScheduledThreadPoolExecutor(schedulerPoolSize, pixExecutor()); // ex.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); return ex; } @Bean public Executor pixExecutor() { final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(executorMaxPoolSize); executor.setQueueCapacity(executorQueueCapacity); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setWaitForTasksToCompleteOnShutdown(true); return executor; } 而不是3,它将在关闭之前完成任务。

    String line = scanner.nextLine();
    String outputLine = line.replace('?', '-');
    outputLine = outputLine.replace('.', ' ');
    writer.println(outputLine);