Я использую декларативные транзакции Spring (аннотация @Transactional) в режиме "aspectj". Он работает в большинстве случаев точно так, как должен, но для одного он этого не делает. Мы можем назвать его Lang
(потому что это то, что он на самом деле называл).
Я смог точно определить проблему для ткача времени. Включив отладку и подробное ведение журнала в файле aop.xml, он перечисляет все сотканные классы. Проблематичный класс Lang
вообще не упоминается в журналах.
Затем я помещаю точку останова в начало Lang
, заставляя Eclipse приостанавливать поток при загрузке класса Lang
. Эта точка останова поражается, когда LTW переплетает другие классы! Поэтому я угадываю, что он либо пытается переплетать Lang
, и терпит неудачу, и не выводит его, либо какой-либо другой класс имеет ссылку, которая заставляет его загружать Lang
, прежде чем он действительно получит возможность переплетать его.
Однако я не уверен, как продолжать отлаживать это, так как я не могу воспроизвести его в меньших масштабах. Любые предложения о том, как продолжить?
Обновление. Другие подсказки также приветствуются. Например, как работает LTW? Кажется, что происходит много магии. Есть ли какие-либо опции для получения еще более отладочной информации от LTW? В настоящее время у меня есть:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
Я забыл упомянуть об этом раньше: spring -agent используется для разрешения LTW, т.е. InstrumentationLoadTimeWeaver
.
Основываясь на предложениях Энди Клемента, я решил проверить, прошел ли какой-либо трансформатор AspectJ даже класс. Я поставил точку останова в ClassPreProcessorAgent.transform(..)
, и кажется, что класс Lang
никогда не достигает этого метода, несмотря на то, что он загружается одним и тем же загрузчиком классов, как и другие классы (экземпляр Jetty WebAppClassLoader).
Затем я включил точку останова в InstrumentationLoadTimeWeaver$FilteringClassFileTransformer.transform(..)
. Даже для этого не выбрано значение Lang
. И я считаю, что этот метод следует вызывать для всех загруженных классов, независимо от того, какой класс загрузчик они используют. Это начинает выглядеть так:
- Проблема с моей отладкой. Возможно,
Lang
не загружается в то время, когда Eclipse сообщает, что он - Ошибка Java? Надуманный, но я предполагаю, что это произойдет.
Следующий ключ: я включил -verbose:class
, и кажется, что Lang
загружается преждевременно - возможно, до того, как трансформатор будет добавлен в Инструментарий. Как ни странно, моя точка останова Eclipse не поймает эту нагрузку.
Это означает, что Spring является новым подозреваемым. в ConfigurationClassPostProcessor
есть некоторая обработка, которая загружает классы для их проверки. Это может быть связано с моей проблемой.
Эти строки в ConfigurationClassBeanDefinitionReader
приводят к чтению класса 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()
вызывает getDeclaredMethods()
в классе, который загружает все классы параметров всех методов в этом классе. Я предполагаю, что это, возможно, не конец проблемы, потому что я думаю, что классы должны быть выгружены. Может ли JVM кэшировать экземпляр класса по непознаваемым причинам?