J'utilise les transactions déclaratives de Spring (l'annotation @Transactional) en mode "aspectj". Cela fonctionne dans la plupart des cas exactement comme il se doit, mais pour un, ce n'est pas le cas. Nous pouvons l'appeler Lang
(parce que c'est ce qu'on appelle en fait).AspectJ Load Weaver ne détecte pas toutes les classes
J'ai pu identifier le problème au tisserand de chargement. En activant le débogage et la journalisation détaillée dans aop.xml, il répertorie toutes les classes en cours de tissage. La classe problématique Lang
n'est en effet pas mentionnée dans les journaux.
Ensuite, je mets un point d'arrêt en haut de Lang
, provoquant Eclipse pour suspendre le thread lorsque la classe Lang
est chargée. Ce point d'arrêt est atteint pendant que le LTW tisse d'autres classes! Donc, je devine qu'il essaye ou non de tisser Lang
et échoue et ne produit pas cela, ou une autre classe a une référence qui l'oblige à charger Lang
avant qu'il ne puisse réellement le tisser.
Je ne suis pas sûr cependant comment continuer à déboguer cela, puisque je ne suis pas capable de le reproduire à plus petite échelle. Des suggestions sur comment continuer?
Mise à jour: D'autres indices sont également les bienvenus. Par exemple, comment fonctionne le LTW? Il semble y avoir beaucoup de magie qui se passe. Y at-il des options pour obtenir encore plus de sortie de débogage de la LTW? J'ai actuellement:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
J'ai oublié tom mentionner avant: printemps agent est utilisé pour permettre LTW, à savoir le InstrumentationLoadTimeWeaver
. Sur la base des suggestions d'Andy Clément, j'ai décidé d'inspecter si le transformateur AspectJ est même passé la classe. J'ai mis un point d'arrêt dans ClassPreProcessorAgent.transform(..)
, et il semble que la classe Lang
n'atteint jamais cette méthode, bien qu'elle soit chargée par le même chargeur de classe que les autres classes (une instance de WebAppClassLoader de Jetty). J'ai ensuite ajouté un point d'arrêt au InstrumentationLoadTimeWeaver$FilteringClassFileTransformer.transform(..)
. Même pas celui-là est frappé pour Lang
. Et je crois que cette méthode devrait être appelée pour toutes les classes chargées, quel que soit le chargeur de classe qu'ils utilisent. Cela commence à ressembler à:
- Un problème avec mon débogage. Peut-être
Lang
n'est pas chargé au moment où Eclipse signale il est - Java bug? Farfelu, mais je suppose que ça arrive.
idée suivante: je me suis tourné sur -verbose:class
et il semble que Lang
est en cours de chargement prématurément - probablement avant que le transformateur est ajouté à Instrumentation. Bizarrement, mon point d'arrêt Eclipse n'attrape pas ce chargement.
Cela signifie que Spring est un nouveau suspect. il semble y avoir un traitement dans ConfigurationClassPostProcessor
qui charge des classes pour les inspecter. Cela pourrait être lié à mon problème.
Ces lignes ConfigurationClassBeanDefinitionReader
cause la classe à lire Lang
:
else if (metadata.isAnnotated(Component.class.getName()) ||
metadata.hasAnnotatedMethods(Bean.class.getName())) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
return true;
}
metadata.hasAnnotatedMethods()
En particulier, les appels getDeclaredMethods()
la classe, qui charge toutes les classes de paramètres de toutes les méthodes de cette classe. Je suppose que ce n'est peut-être pas la fin du problème, car je pense que les classes sont censées être déchargées. La JVM peut-elle mettre en cache l'instance de la classe pour des raisons inconnaissables?
Merci pour la réponse. Idée intéressante que la chaîne "Lang" pourrait poser problème. Mais j'aurais dû le mentionner, il y a d'autres classes (au moins une) qui ne sont pas non plus tissées. L'autre connu s'appelle CommServer. Donc je doute que ce soit le problème. Je devrais peut-être commencer à regarder la source AspectJ, cependant. – waxwing