Я использую декларативные транзакции Spring (аннотацию @Transactional) в режиме аспекта. В большинстве случаев он работает точно так же, как и должен, но для одного - нет. Мы можем назвать это 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
даже не достигает этого метода, несмотря на то, что он загружается тем же загрузчиком классов, что и другие классы (экземпляр WebAppClassLoader Jetty).
Затем я установил точку останова в 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 кэшировать экземпляр класса по неизвестным причинам?