Question

Je veux savoir ce qui se passe réellement lorsque vous annotez une méthode avec @Transactional? Bien sûr, je sais que le printemps enveloppera cette méthode dans une transaction.

Mais j'ai les doutes suivants:

  1. J'ai entendu dire que le printemps crée un classe proxy? Quelqu'un peut-il expliquer cela dans plus profondeur. Qu'est-ce qui réside réellement dans cette classe de proxy? Qu'arrive-t-il à la classe réelle? Et comment puis-je voir la classe proxielle créée de Spring
  2. J'ai également lu dans les documents de printemps qui:

Remarque: Puisque ce mécanisme est basé sur des procurations, Seuls les appels de méthode «externes» qui arrivent par le proxy seront interceptés. Cela signifie que «l'auto-invocation», c'est-à-dire une méthode dans l'objet cible, appelant une autre méthode de l'objet cible, ne conduira pas à une transaction réelle lors de l'exécution même si la méthode invoquée est marquée avec @Transactional!

La source: http://stating.springsource.org/spring/docs/2.0.x/reference/transaction.html

Pourquoi seuls les appels de méthode externe seront sous transaction et non les méthodes d'auto-invocation?

Était-ce utile?

La solution

C'est un grand sujet. Le doc de référence de ressort y consacre plusieurs chapitres. Je recommande de lire ceux sur Programmation orientée vers l'aspect et Transactions, comme le support de transaction déclaratif de Spring utilise AOP dans sa fondation.

Mais à un niveau très élevé, le printemps crée des procurations pour les classes qui déclarent @Transactional sur la classe elle-même ou sur les membres. Le proxy est principalement invisible au moment de l'exécution. Il fournit un moyen pour le printemps d'injecter des comportements avant, après, ou autour des appels de méthode dans l'objet proxés. La gestion des transactions n'est qu'un exemple des comportements qui peuvent être accrochés. Les vérifications de sécurité en sont une autre. Et vous pouvez également fournir le vôtre pour des choses comme l'exploitation forestière. Donc lorsque vous annotez une méthode avec @Transactional, Spring crée dynamiquement un proxy qui implémente les mêmes interfaces que la classe que vous annotez. Et lorsque les clients font des appels dans votre objet, les appels sont interceptés et les comportements injectés via le mécanisme de proxy.

Soit dit en passant, les transactions dans l'EJB fonctionnent.

Comme vous l'avez observé, le mécanisme proxy ne fonctionne que lorsque les appels proviennent d'un objet externe. Lorsque vous passez un appel interne dans l'objet, vous passez vraiment un appel via "cette"Référence, qui contourne le proxy. Il existe cependant des moyens de contourner ce problème. J'explique une approche dans Ce message de forum dans lequel j'utilise un BeanfactoryPostprocessor Pour injecter une instance du proxy en classes "auto-références" à l'exécution. J'enregistre cette référence à une variable de membre appelée "moi". Alors si j'ai besoin de passer des appels internes qui nécessitent un changement dans l'état de la transaction du fil, je dirige l'appel via le proxy (par exemple"me.somemethod ()".) Le post du forum explique plus en détail. Notez que le BeanfactoryPostprocessor Le code serait un peu différent maintenant, car il a été écrit dans le calendrier Spring 1.x. Mais j'espère que cela vous donne une idée. J'ai une version mise à jour que je pourrais probablement mettre à disposition.

Autres conseils

Lorsque Spring charge vos définitions de bean et a été configuré pour rechercher des annotations @transactionnelles, il créera ces objets proxy autour de votre haricot réel. Ces objets proxy sont des instances de classes qui sont générées automatiquement au moment de l'exécution. Le comportement par défaut de ces objets proxy lorsqu'une méthode est invoquée est simplement d'invoquer la même méthode sur le bean "cible" (c'est-à-dire votre haricot).

Cependant, les indicateurs peuvent également être fournis avec des intercepteurs, et lorsqu'ils sont présents, ces intercepteurs seront invoqués par le proxy avant qu'il invoque la méthode de votre haricot cible. Pour les haricots cibles annotés avec @Transactional, Spring créera une transaction Interceptor et le transmettra à l'objet proxy généré. Ainsi, lorsque vous appelez la méthode à partir du code client, vous appelez la méthode sur l'objet proxy, qui invoque d'abord la transaction Interceptor (qui commence une transaction), qui invoque à son tour la méthode sur votre bean cible. Lorsque l'invocation se termine, la transaction Interceptor engage / fait reculer la transaction. Il est transparent pour le code client.

Quant à la chose "méthode externe", si votre haricot invoque l'une de ses propres méthodes, il ne le fera pas via le proxy. N'oubliez pas que le printemps enveloppe votre haricot dans le proxy, votre haricot n'a aucune connaissance. Seuls les appels de «l'extérieur» de votre haricot passent par le proxy.

Est ce que ça aide?

En tant que personne visuelle, j'aime peser avec un diagramme de séquence du motif proxy. Si vous ne savez pas lire les flèches, j'ai lu la première comme ceci: Client exécution Proxy.method().

  1. Le client appelle une méthode sur la cible de son point de vue et est silencieusement interceptée par le proxy
  2. Si un aspect avant est défini, le proxy l'exécutera
  3. Ensuite, la méthode réelle (cible) est exécutée
  4. La reprise après le retour et le suivi sont des aspects facultatifs qui sont exécutés après le retour de la méthode et / ou si la méthode lance une exception
  5. Après cela, le proxy exécute l'aspect après (s'il est défini)
  6. Enfin, le proxy revient au client d'appel

Proxy Pattern Sequence Diagram(J'ai été autorisé à publier la photo à condition que j'ai mentionné ses origines. Auteur: Noel Vaes, site Web: www.noelvaes.eu)

La réponse la plus simple est, Sur la méthode que vous déclarez @Transactionnelle, la limite de la transaction démarre et la limite se termine lorsque la méthode se termine.

Si vous utilisez JPA Call, tous les validations sont avec dans cette limite de transaction. Disons que vous épargnez Entity1, Entity2 et Entity3. Désormais, alors que SAVING ETITY3, une exception se produit, alors que Enitiy1 et Entity2 sont disponibles dans la même transaction, donc Entity1 et Entity2 seront enracinés avec Entity3.

Transaction: (Entity1.Save, Entity2.save, Entity3.Save). Toute exception entraînera un recul de toutes les transactions JPA avec DB. La transaction JPA en interne est utilisée par Spring.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top