Utilisation de l'annotation @Async dans Spring Framework

Introduction

L'annotation @Async de Spring Framework permet d'exécuter des méthodes de manière asynchrone dans une application Spring, ce qui est idéal pour les opérations gourmandes en temps sans bloquer le thread principal. Ce guide explique comment l'implémenter et fournit des exemples de code adaptés.

Activation du support asynchrone

Pour activer l'exécution asynchrone, ajoutez l'annotation @EnableAsync à votre classe de configuration ou principale.

@EnableAsync
public class AppConfig {
    public static void main(String[] args) {
        SpringApplication.run(AppConfig.class, args);
    }
}

Définition des méthodes asynchrones

Utilisez @Async sur les méthodes des beans Spring, par exemple dans un service, pour les marquer comme asynchrones. Vous pouvez lier un exécuteur spécifique.

@Service
public class ProcessingService {
    
    @Async(executor = "asyncExecutor")
    public void executeBackgroundTask() {
        // Logique pour une tâche asynchrone
    }

    @Async(executor = "asyncExecutor")
    public CompletableFuture<Data> fetchDataAsynchronously() {
        // Exécution asynchrone avec retour de résultat
        return CompletableFuture.completedFuture(new Data());
    }
}

Invocation des méthodes asynchrones

L'appel à une méthode asynchrone se fait normalement, mais elle s'exécute en arrière-plan, permettant au code appelant de continuer immédiatement.

@Service
public class InvokerService {
    
    @Resource
    private ProcessingService processingService;

    public void startTask() {
        processingService.executeBackgroundTask();
        // Le code se poursuit sans attendre la fin de la tâche
    }
}

Configuration d'un exécuteur personnalisé

Vous pouvez définir un exécuteur de threads personnalisé pour contrôler l'exécution asynchrone. Sans cela, Spring utilise une implémentation par défaut.

@Bean(name = "asyncExecutor")
public Executor customExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(8);
    executor.setMaxPoolSize(16);
    executor.setQueueCapacity(200);
    executor.initialize();
    return executor;
}

Pour appliquer cet exécuteur à toutes les méthodes @Async, configurez-le comme exécuteur par défaut dans une classe de configuration.

@Configuration
@EnableAsync
public class AsynchConfiguration extends AsyncConfigurationSupport {

    @Bean(name = "asyncExecutor")
    public Executor customExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(8);
        executor.setMaxPoolSize(16);
        executor.setQueueCapacity(200);
        executor.initialize();
        return executor;
    }

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

Points d'attention

  • Les méthodes annotées @Async doivent être appelées depuis des composants Spring gérés.
  • Elles ne sont pas compatibles avec les constructeurs, @PostConstruct ou @PreDestroy.
  • Les exceptions survenant dans ces méthodes ne remontent pas à l'appelant ; elles doivent être capturées localement.
  • La propagation des transactions n'est pas prise en charge car l'exécution se fait sur des threads distincts.
  • Pour récupérer des résultats, utilisez Future ou CompletableFuture comme type de retour.
  • Les ressources partagées dans ces méthodes doivent être thread-safe pour éviter les problèmes de concurrence.
  • Le SimpleAsyncTaskExecutor par défaut peut générer une surcharge ; une configuration personnalisée est recommadnée.
  • Le débogage et la journalisation peuvent être compliqués en raison de l'exécution multi-thread.
  • Implémentez une gestion des erreurs robuste, par exemple via l'attribut noResultException de @Async.

Étiquettes: Spring Framework Java Annotations asynchronous programming ThreadPool

Publié le 29 juin à 03h33