2010-07-28 6 views
0

Si j'ai une classe gérée transactionnellement, dans lequel j'ai deux méthodes par exemple Gestion transactionnelle de printemps - Où placer les annotations?

void OuterMethod(Data somedata) 
{ 
    this.InnerMethod(somedata) 
} 

@Transactional("mymanager") 
void InnerMethod(Data somedata) 
{ 
    //writes some things 
} 

est-ce valable? Je ne peux pas l'obtenir pour écrire dans la base de données pour une raison quelconque, même si cela ne me donne aucune erreur.

+1

note: par convention, les noms de méthodes en Java commencent par une minuscule (c'est-à-dire outerMethod(), innerMethod()) – sfussenegger

Répondre

2

Le ressort n'utilise pas de code bytecode instrumentation pour la mise en œuvre de l'AOP. Donc il est prévisible que si une méthode de un objet mandaté appelle une autre méthode dans le même objet, l'aspect ne sera pas appliqué à l'appel de méthode. Spring permet cependant d'appliquer l'aspect à cet appel de méthode en définissant exposeProxy sur True et en utilisant AopContext .currentProxy().

Les informations pourraient être un peu daté, mais à ma connaissance, il est toujours précis (pas sûr du drapeau « exposeProxy » bien)

Voir http://forum.springsource.org/showthread.php?t=9926

+0

Désolé - Je ne connais pas grand chose à Java ou à Spring. Cela vous dérange-t-il de clarifier cela? Cela signifie-t-il que je devrais juste annoter OuterMethod? –

+1

Oui, c'est essentiellement l'essence de celui-ci. Le problème est que la gestion des transactions est dans un objet différent. Par conséquent vous appelez proxy.OuterMethod() -> service.OuterMethod() -> service.InnerMethod(), tout votre traitement de transaction est dans proxy.InnerMethod(), qui n'est pas accessible à partir de service.OuterMethod() - non sans utiliser AopContext.currentProxy() qui serait une solution de contournement plutôt laide. Donc oui, annote OuterMethod() ou même les deux. – sfussenegger

+0

C'est vrai. L'alternative aux proxies est d'utiliser AspectJ AOP, soit par tissage en temps de chargement (laid, doit remplacer le chargeur de classe) ou par tissage à la compilation (complique le processus de construction, mais un bon support d'outil avec Eclipse et Maven). – Henning

0

Ceci est un sujet délicat. Lorsque Spring trouve l'annotation @Transactional, il crée un proxy pour votre objet, en utilisant l'intermédiaire de l'intermédiaire de l'interface JDK ou de la sous-classe CGLIB. Dans les deux cas, le mandataire ne fonctionnera que pour méthodes publiques. Je simplifie peut-être un peu les choses, mais c'est l'idée générale.

Ainsi, même si un objet proxy peut encore être généré pour gérer le InnerMethod() annoté, il ne sera pas réellement appelé, puisque les méthodes non publiques vont "tomber à travers les fissures". Ce serait bien que Spring vous avertisse à ce sujet, mais ce n'est pas le cas.

La solution simple est de vous assurer que vos annotations sont sur des méthodes publiques.