Я пишу весеннее загрузочное приложение с помощью ThreadPoolTaskExecutor. Вот мой класс приложения:
import info.gandraweb.apns.service.MessageService;
import info.gandraweb.apns.settings.AppSettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@SpringBootApplication
@EnableScheduling
@EnableAutoConfiguration
@EnableAsync
public class Application implements AsyncConfigurer{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
@Autowired
private AppSettings appSettings;
public static void main(String[] args) {
ApplicationContext applicationContext = SpringApplication.run(Application.class, args);
AppSettings appSettings = applicationContext.getBean(AppSettings.class);
logger.info(appSettings.toString());
test(applicationContext);
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setThreadNamePrefix("MyExecutor-");
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(50);
taskExecutor.setQueueCapacity(1000);
taskExecutor.setWaitForTasksToCompleteOnShutdown(true);
taskExecutor.initialize();
return taskExecutor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
private static void test(ApplicationContext applicationContext) {
MessageService messageService = applicationContext.getBean(MessageService.class);
messageService.processNewMessages();
}
}**
внутри метода тестирования, который я вызываю
messageService.processNewMessages()
который, в свою очередь, если существует какая-то задача в БД, вызывает метод Async на другом bean-компоненте для его обработки. Когда нет задач для обработки, приложение завершается.
Если в БД есть какие-либо задачи для обработки после выполнения, приложение продолжает работать и никогда не завершается .... похоже, что метод shutdown () в ThreadPoolTaskExecutor никогда не вызывается?
Затем я реализовал интерфейс ApplicationListener и зарегистрировал, что происходит внутри onApplicationEvent(ContextClosedEvent)
Поэтому, когда нет задачи для обработки завершения приложения и срабатывает ContextClosedEvent. Если есть какие-то задачи в БД для обработки после выполнения ContextClosedEvent не срабатывает???
Когда я удаляю AsyncConfigurer из приложения, срабатывает ContextClosedEvent, и приложение закрывается. Но в таком случае я потерял возможность настроить ThreadPoolTaskExecutor.
Итак, как я могу настроить ThreadPoolTaskExecutor и управлять изящным завершением этого исполнителя или запускать ContextClosedEvent... каков бы ни был предпочтительный способ его изящного завершения?