C'est un sujet important. Le document de référence de Spring y consacre plusieurs chapitres. Je vous recommande de lire ceux sur Programmation orientée aspects y Transactions Le support déclaratif des transactions de Spring est basé sur la POA.
Mais à un niveau très élevé, Spring crée des proxies pour les classes qui déclarent @Transactional
sur la classe elle-même ou sur les membres. Le proxy est le plus souvent invisible au moment de l'exécution. Il permet à Spring d'injecter des comportements avant, après ou autour des appels de méthode dans l'objet proxyé. La gestion des transactions n'est qu'un exemple des comportements qui peuvent être injectés. Les contrôles de sécurité en sont un autre. Et vous pouvez également fournir vos propres comportements, pour des choses comme la journalisation. Ainsi, lorsque vous annotez une méthode avec @Transactional
En effet, Spring crée dynamiquement un proxy qui implémente la ou les mêmes interfaces que la classe que vous annotez. Et lorsque les clients font des appels à votre objet, les appels sont interceptés et les comportements injectés via le mécanisme de proxy.
Les transactions dans EJB fonctionnent de manière similaire, d'ailleurs.
Comme vous l'avez observé, à travers, le mécanisme de proxy ne fonctionne que lorsque les appels proviennent d'un objet externe. Lorsque vous effectuez un appel interne à l'objet, vous effectuez en réalité un appel par le biais du mécanisme de proxy. this
ce qui permet de contourner le proxy. Il existe toutefois des moyens de contourner ce problème. J'explique une approche dans ce message du forum dans lequel j'utilise un BeanFactoryPostProcessor
pour injecter une instance du proxy dans les classes "auto-référencées" au moment de l'exécution. Je sauvegarde cette référence dans une variable membre appelée me
. Ensuite, si j'ai besoin d'effectuer des appels internes qui nécessitent un changement de l'état de la transaction du thread, je dirige l'appel à travers 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 aujourd'hui, puisqu'il a été écrit à l'époque de Spring 1.x. Mais j'espère que cela vous donnera une idée. J'ai une version mise à jour que je pourrais probablement mettre à disposition.
2 votes
La discussion pertinente est ici : stackoverflow.com/questions/3120143/