


Dans les applications Spring modernes, il est courant de combiner l'exécution asynchrone avec un comportement transactionnel. Cependant, annoter une méthode avec @Async et @Transactional(propagation = Propagation.REQUIRES_NEW) peut entraîner un comportement inattendu car Spring gère les tâches et les transactions asynchrones.
Dans cet article, nous explorerons le problème en détail et démontrerons une solution permettant de gérer correctement à la fois l'exécution asynchrone et la gestion des transactions.
Le problème : @Async et @Transactional(propagation = Propagation.REQUIRES_NEW)
Considérez l'extrait de code suivant :
@Async @Transactional(propagation = Propagation.REQUIRES_NEW) public void saveSomething() { // save-point one // save-point two }
À première vue, il peut sembler que tout fonctionne comme prévu. Cependant, cette configuration présente certains problèmes clés qui peuvent entraîner un comportement involontaire.
Que se passe-t-il dans les coulisses ?
- Annotation @Async :
L'annotation @Async indique à Spring d'exécuter la méthode de manière asynchrone dans un thread séparé. Cela signifie que la méthode ne s'exécutera pas dans le thread d'origine qui l'a appelée mais sera déchargée vers un autre thread dans un pool de threads.
Spring utilise des proxys pour gérer les méthodes asynchrones. Lorsque vous appelez une méthode annotée avec @Async, Spring délègue l'exécution à un exécuteur interne qui exécute la méthode dans un thread différent.
- @Transactional(propagation = Propagation.REQUIRES_NEW) Annotation :
L'annotation @Transactional(propagation = Propagation.REQUIRES_NEW) garantit qu'une nouvelle transaction est démarrée pour la méthode, quelle que soit toute transaction existante. Il suspend toute transaction active dans le thread appelant et commence une nouvelle transaction pour la méthode.
La gestion des transactions dans Spring est généralement liée au thread, ce qui signifie que le contexte de la transaction est lié au thread actuel.
Le conflit
Le problème se pose parce que @Async exécute la méthode dans un thread différent et que la gestion des transactions de Spring s'appuie sur le thread pour lier la transaction. Lorsque la méthode est exécutée de manière asynchrone, le contexte de transaction du thread appelant ne se propage pas au nouveau thread, ce qui entraîne les problèmes suivants :
- L'annotation @Transactional ne créera pas de nouvelle transaction dans le thread asynchrone et tout comportement transactionnel (comme les annulations, les validations, etc.) ne sera pas géré correctement.
- Le paramètre de propagation REQUIRES_NEW ne s'appliquera pas car la méthode asynchrone s'exécute en dehors du contexte de transaction d'origine.
La solution : découpler l'exécution asynchrone et les transactions
Pour résoudre ce problème, vous pouvez découpler l'exécution asynchrone de la logique transactionnelle en traitant la transaction dans une méthode de service distincte. Voici comment procéder :
Étape 1 : Créer un nouveau service synchrone pour la logique transactionnelle
Créez un nouveau service qui gère la logique transactionnelle. Cette méthode sera exécutée de manière synchrone (sans @Async) pour garantir que la gestion des transactions fonctionne comme prévu.Étape 2 : Appeler la méthode synchrone de manière asynchrone
Vous pouvez ensuite appeler la méthode transactionnelle synchrone de manière asynchrone en utilisant @Async. Cela garantit que la logique transactionnelle est gérée correctement dans le thread principal et que le comportement asynchrone est toujours maintenu.
Voici à quoi ressemble le code refactorisé :
@Async @Transactional(propagation = Propagation.REQUIRES_NEW) public void saveSomething() { // save-point one // save-point two }
Comment ça marche ?
Dans la solution refactorisée, l'exécution asynchrone est obtenue en annotant la méthode saveSomethingAsync() avec @Async. Cela signifie que lorsque saveSomethingAsync() est appelé, il s'exécutera dans un thread séparé géré par l'exécuteur de tâches asynchrone de Spring. L'exécuter dans un thread différent permet au thread principal de poursuivre son exécution sans attendre la fin de saveSomethingAsync(). Cette approche est bénéfique pour les scénarios dans lesquels vous souhaitez vous décharger de tâches de longue durée, améliorer la réactivité ou gérer simultanément des opérations indépendantes.
Pour le comportement transactionnel, la méthode saveSomething() dans TransactionalService est annotée avec @Transactional(propagation = Propagation.REQUIRES_NEW). Cela garantit que chaque appel à saveSomething() crée une nouvelle transaction indépendante de toute transaction existante dans la méthode appelante. La propagation REQUIRES_NEW démarre une nouvelle transaction et suspend toute transaction existante, permettant à saveSomething() de fonctionner dans un contexte de transaction isolé. Cela signifie que même si la méthode appelante d'origine a une transaction, saveSomething() fonctionnera au sein de sa propre transaction distincte, permettant des validations et des annulations contrôlées pour cette opération uniquement.
En dissociant l'exécution asynchrone de la logique transactionnelle, nous garantissons que la gestion des transactions fonctionne comme prévu. Dans cette configuration, le contexte de transaction reste correctement géré dans la méthode saveSomething(), tandis que la méthode saveSomethingAsync() continue de s'exécuter dans un thread séparé. Cette séparation des préoccupations permet à la fois de bénéficier des avantages du traitement asynchrone et d'une gestion fiable des transactions, permettant des opérations de données indépendantes et sûres même lors d'un traitement simultané.
Quand utiliser cette approche ?
Lorsque l'isolation des transactions est critique : Si vous devez vous assurer que certaines opérations sont effectuées dans une transaction distincte (c'est-à-dire REQUIRES_NEW), cette approche fonctionne bien.
Opérations asynchrones : Si vous avez des tâches indépendantes de longue durée qui doivent être exécutées de manière asynchrone mais qui nécessitent également leurs propres limites de transaction.
Alternative : utiliser une file d'attente de messages pour un découplage complet
Si vous avez besoin d'un découplage plus avancé ou si vous souhaitez gérer les tentatives, la gestion des erreurs et les processus de longue durée, envisagez de décharger la tâche vers une file d'attente de messages comme Kafka ou RabbitMQ. En utilisant une file d'attente de messages, vous pouvez garantir que chaque tâche s'exécute dans son propre contexte et que la transaction peut être gérée indépendamment.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Comment Java atténue des problèmes spécifiques à la plate-forme? Java implémente la plate-forme indépendante de la plate-forme via JVM et des bibliothèques standard. 1) Utilisez Bytecode et JVM pour abstraction des différences du système d'exploitation; 2) La bibliothèque standard fournit des API multiplateformes, telles que les chemins de fichier de traitement des classes de chemins et le codage des caractères de traitement de la classe Charset; 3) Utilisez des fichiers de configuration et des tests multiplateformes dans les projets réels pour l'optimisation et le débogage.

Java'splatformIndependanceNhancesMicRoservices ArchitectureByoFerringDeploymentFlexibilité, cohérence, évolutivité, etportabilité.1) DeploymentFlexibilityAllowsMicroserviceStorUnonanyPlatformwithajvm.2) CohérenceaCossserviceSiceSIGLYPLATFORMWithajvm.2)

Graalvm améliore l'indépendance de la plate-forme de Java de trois manières: 1. Interopérabilité transversale, permettant à Java d'interopérer de manière transparente avec d'autres langues; 2. 3. Optimisation des performances, le compilateur Graal génère un code machine efficace pour améliorer les performances et la cohérence des programmes Java.

ToeffectivetestjavaapplicationsforPlatformCompatibilité, suivi de l'essence: 1) SetUpAutomatedStestingacrossMultipleplatformSusingcitoolslikejenkinsorgithubacts.

Le compilateur Java réalise l'indépendance de la plate-forme de Java en convertissant le code source en bytecode indépendant de la plate-forme, permettant aux programmes Java d'exécuter sur n'importe quel système d'exploitation avec JVM installé.

ByteCodeachievesPlatformIndependanceBeBeingExEcutedByaVirtualmachine (VM), permettant à la codétorunonanyplatformwiththeappo pourpropriév.forexample, javabytecocecanrunonanydevicewithajvm, permettre de "writeonce, runanywhere" fonctionnalité.

Java ne peut pas atteindre l'indépendance de la plate-forme à 100%, mais son indépendance de la plate-forme est implémentée via JVM et ByteCode pour s'assurer que le code s'exécute sur différentes plates-formes. Les implémentations spécifiques incluent: 1. Compilation dans ByteCode; 2. Interprétation et exécution de JVM; 3. Cohérence de la bibliothèque standard. Cependant, les différences de mise en œuvre de JVM, les différences de système d'exploitation et de matériel et la compatibilité des bibliothèques tierces peuvent affecter l'indépendance de sa plate-forme.

Java réalise l'indépendance de la plate-forme via "Écrire une fois, exécuter partout" et améliore la maintenabilité du code: 1. Réutilisation du code élevé et réduit le développement en double; 2. Coût de maintenance faible, une seule modification est requise; 3. L'efficacité de collaboration d'équipe élevée est élevée, pratique pour le partage des connaissances.


Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

SublimeText3 Linux nouvelle version
Dernière version de SublimeText3 Linux

DVWA
Damn Vulnerable Web App (DVWA) est une application Web PHP/MySQL très vulnérable. Ses principaux objectifs sont d'aider les professionnels de la sécurité à tester leurs compétences et leurs outils dans un environnement juridique, d'aider les développeurs Web à mieux comprendre le processus de sécurisation des applications Web et d'aider les enseignants/étudiants à enseigner/apprendre dans un environnement de classe. Application Web sécurité. L'objectif de DVWA est de mettre en pratique certaines des vulnérabilités Web les plus courantes via une interface simple et directe, avec différents degrés de difficulté. Veuillez noter que ce logiciel

PhpStorm version Mac
Le dernier (2018.2.1) outil de développement intégré PHP professionnel

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

MinGW - GNU minimaliste pour Windows
Ce projet est en cours de migration vers osdn.net/projects/mingw, vous pouvez continuer à nous suivre là-bas. MinGW : un port Windows natif de GNU Compiler Collection (GCC), des bibliothèques d'importation et des fichiers d'en-tête librement distribuables pour la création d'applications Windows natives ; inclut des extensions du runtime MSVC pour prendre en charge la fonctionnalité C99. Tous les logiciels MinGW peuvent fonctionner sur les plates-formes Windows 64 bits.
