Завершение работы @Bean ExecutorService с использованием @PreDestroy

У меня есть класс Spring @Configuration следующим образом:

@Configuration
public class ExecutorServiceConfiguration {

    @Bean
    public BlockingQueue<Runnable> queue() {
        return ArrayBlockingQueue<>(1000);
    }     

    @Bean
    public ExecutorService executor(BlockingQueue<Runnable> queue) {
        return ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, queue);
    }

    @PreDestroy
    public void shutdownExecutor() {
        // no executor instance
    }
}

Я также хотел бы указать @PreDestroy метод, который закрывает ExecutorService. Тем не менее @PreDestroy Метод не может иметь никаких аргументов, поэтому я не могу передать executor боб к этому методу, чтобы закрыть его. Указание метода уничтожения в @Bean(destroyMethod = "...") тоже не работает. Это позволяет мне указать существующие shutdown или же shutdownNow, но не пользовательский метод, который я намерен использовать.

Я знаю, что мог бы создать экземпляр очереди и исполнителя напрямую, а не как компоненты Spring, но я бы предпочел сделать это таким образом.

2 ответа

Решение

Я люблю определять классы inline:

@Bean(destroyMethod = "myCustomShutdown")
public ExecutorService executor(BlockingQueue<Runnable> queue) {
    return new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, queue) {
        public void myCustomShutdown() {
            ...
        }
    };
}

Использовать ThreadPoolTaskExecutor который делает все это по умолчанию.

@Configuration
public class ExecutorServiceConfiguration {

    @Bean
    public ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor() {
            protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
                return new ArrayBlockingQueue(queueCapacity);
            }
        };
        taskExecutor.setCorePoolSize(1);
        taskExecutor.setMaxPoolSize(1);
        taskExecutor.setKeepAliveSeconds(0);
        setQueueCapacity(1000);
        return taskExecutor;
    }    
}

Это настроит ThreadPoolExecutor и выключение, когда приложение останавливается.

Если вам не нужно ArrayBlockingQueue но может жить по умолчанию LinkedBlockingQueue и только нужно указать емкость очереди, вы можете удалить переопределение createQueue метод.

Другие вопросы по тегам