O tecelão do tempo de carregamento do AspectJ não detecta todas as classes
Estou usando as transações declarativas do Spring (a anotação @Transactional) no modo "aspectj". Na maioria dos casos, funciona exatamente como deveria, mas para um não. Podemos chamá-loLang
(porque é assim que se chama).
Consegui identificar o problema no tecelão do tempo de carregamento. Ativando o log detalhado e de depuração no aop.xml, ele lista todas as classes que estão sendo tecidas. A classe problemáticaLang
de fato não é mencionado nos logs.
Então eu coloquei um ponto de interrupção no topoLang
, fazendo com que o Eclipse suspenda o encadeamento quando oLang
classe é carregada. Este ponto de interrupção é atingido enquanto o LTW tece outras classes! Então, eu acho que ele tenta tecerLang
e falha e não gera isso, ou alguma outra classe tem uma referência que o força a carregarLang
antes que ele tenha a chance de tecê-lo.
No entanto, não tenho certeza de como continuar depurando isso, pois não consigo reproduzi-lo em menor escala. Alguma sugestão de como continuar?
Atualizar: Outras pistas também são bem-vindas. Por exemplo, como o LTW realmente funciona? Parece haver muita mágica acontecendo. Existem opções para obter ainda mais saída de depuração do LTW? Eu tenho atualmente:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
Esqueci-me de mencioná-lo antes:agente de mola está sendo usado para permitir LTW, ou seja, oInstrumentationLoadTimeWeaver
.
Com base nas sugestões de Andy Clement, decidi inspecionar se o transformador AspectJ já passou na classe. Eu coloquei um ponto de interrupção emClassPreProcessorAgent.transform(..)
e parece que oLang
A classe nunca chega a esse método, apesar de ser carregada pelo mesmo carregador de classes que outras classes (uma instância do WebAppClassLoader do Jetty).
Eu então coloquei um ponto de interrupção noInstrumentationLoadTimeWeaver$FilteringClassFileTransformer.transform(..)
. Nem mesmo aquele é atingido porLang
. E acredito que esse método deve ser invocado paratudo classes carregadas, independentemente do carregador de classes que eles estão usando. Isso está começando a se parecer com:
Lang
não é carregado no momento em que o Eclipse relata que éBug do Java? Exagerado, mas suponho que isso aconteça.Próxima pista: liguei-verbose:class
e parece queLang
é sendo carregado prematuramente - provavelmente antes de o transformador ser adicionado à Instrumentação. Estranhamente, meu ponto de interrupção do Eclipse não captura esse carregamento.
Isso significa que o Spring é um novo suspeito. parece haver algum processamento emConfigurationClassPostProcessor
que carrega classes para inspecioná-las. Isso pode estar relacionado ao meu problema.
Essas linhas emConfigurationClassBeanDefinitionReader
causa oLang
classe a ser lida:
else if (metadata.isAnnotated(Component.class.getName()) ||
metadata.hasAnnotatedMethods(Bean.class.getName())) {
beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
return true;
}
Em particular,metadata.hasAnnotatedMethods()
chamadasgetDeclaredMethods()
na classe, que carrega todas as classes de parâmetros de todos os métodos nessa classe. Estou supondo que esse não seja o fim do problema, porque acho que as classes devem ser descarregadas. A JVM poderia estar armazenando em cache a instância da classe por razões desconhecidas?