How to go from XML Spring scheduling configuration

2019-02-04 19:11发布

问题:

I am trying to convert the following Spring task xml configuration to a purely code/annotation based version:

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

<task:scheduler id="xyz.scheduler" pool size="${xyz.job.scheduler.pool.size:4}"  />

<task:annotation-driven executor="xyz.executor" scheduler="xyz.scheduler" />

<bean id='xyzProcessor' class="xyz.queueing.QueueProcessor" /> 

<task:scheduled-tasks scheduler="xyz.scheduler" >
    <task:scheduled ref="partitioner" method="createPartitions" cron="${xyz.job.partitioner.interval:0 0 3 * * *}" />
</task:scheduled-tasks>

Per the Spring spec, 28.4.1 (http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html), they say that to go from XML like this:

<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>

to code configuration is as simply as enabling either @EnableScheduling and/or @EnableAsync.

However, I don't see anywhere I can actually instantiate the scheduler. The javadoc for @EnableScheduling (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableScheduling.html) shows how I can get plug in my own created Executor, though I'm not exactly sure what class it should be (I still want to be able to control the pool size, queue capacity, and rejection policy). It also shows how I can schedule my createPartitions method using the configureTasks override. However, I would like to be able to name my scheduler (so I can identify its threads) and control its pool size.

So, I wish to know these things:

1) What class can I use to set the executor fields that the XML has?

2) Is there a way to create a scheduler instance that I can control the name and pool size of?

回答1:

Check out the types AsyncConfigurer, AsyncConfigurerSupport, and SchedulingConfigurer. They are helper types you can use to enhance your @Configuration class with async/scheduling configurations.

Across all of them, and the javadoc of @EnabledAsync, you'll find all the setup methods you need to setup your async/scheduling @Configuration class.

The example given equates

 @Configuration
 @EnableAsync
 public class AppConfig implements AsyncConfigurer {

     @Bean
     public MyAsyncBean asyncBean() {
         return new MyAsyncBean();
     }

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(7);
         executor.setMaxPoolSize(42);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.initialize();
         return executor;
     }

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

with

 <beans>
     <task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/>
     <task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/>
     <bean id="asyncBean" class="com.foo.MyAsyncBean"/>
     <bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/>
 </beans>

SchedulingConfigurer has a similar setup for task:scheduler.



回答2:

If you want more fine-grained control you can additionally implement the SchedulingConfigurer and/or AsyncConfigurer interfaces.

As belows,

Please notice the pools also,

@Configuration
@EnableScheduling
public class CronConfig implements SchedulingConfigurer{

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
         taskRegistrar.setScheduler(taskExecutor());    
    }


     @Bean(destroyMethod="shutdown")
     public Executor taskExecutor() {
         return Executors.newScheduledThreadPool(10);
     }

}

And for the Asyncs,

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.initialize();
        return executor;
    }

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

Note that @EnableAsync and @EnableScheduling has to be there for this to work.