Я использую декларативные транзакции Spring (аннотацию @Transactional) в режиме аспекта. В большинстве случаев это работает точно так же, как и должно, но для одного - нет. Мы можем назвать это Lang
(потому что это то, что он на самом деле называется).
Мне удалось точно определить проблему для ткача времени загрузки. Включив отладку и подробное ведение журнала в aop.xml, он перечисляет все переплетенные классы. Проблемный класс Ланга
действительно вообще не упоминается в журналах.
Затем я ставлю точку останова на вершине Ланга
, вызывая Eclipse приостановить поток, когда загружен класс Lang
. Эта точка останова достигнута, пока LTW ткут другие классы! Так что я предполагаю, что он либо пытается соткать Lang
и терпит неудачу, но не выводит его, либо у некоторого другого класса есть ссылка, которая заставляет его загрузить Lang
, прежде чем он действительно получит шанс чтобы сплести его.
Однако я не уверен, как продолжать отлаживать это, так как я не могу воспроизвести его в меньшем масштабе. Любые предложения о том, как продолжить?
Обновление: Другие подсказки также приветствуются. Например, как на самом деле работает LTW? Кажется, что происходит много магии. Есть ли варианты, чтобы получить еще больше отладочной информации от LTW? В настоящее время у меня есть:
<weaver options="-XnoInline -Xreweavable -verbose -debug -showWeaveInfo">
Я забыл упомянуть об этом раньше: spring-agent используется для разрешения LTW, т.е. то есть, InstrumentationLoadTimeWeaver
.
На основании предложений Энди Клемента я решил проверить, прошел ли когда-либо преобразователь AspectJ класс. Я установил точку останова в ClassPreProcessorAgent.transform (..)
, и кажется, что класс Lang
даже не достигает этого метода, несмотря на то, что он загружается тем же загрузчиком классов, что и другие классы (экземпляр JetA's WebAppClassLoader).
Затем я добавил точку останова в InstrumentationLoadTimeWeaver $ FilteringClassFileTransformer.transform (..)
. Даже тот не попал под Ланга
. И я считаю, что метод должен быть вызван для всех загруженных классов, независимо от того, какой загрузчик классов они используют. Это начинает выглядеть так:
Lang
не загружен в то время, когда Eclipse сообщает, что это Следующая подсказка: я включил -verbose: class
, и кажется, что Лэнг
загружается преждевременно - вероятно, прежде чем трансформатор будет добавлен в приборостроение. Как ни странно, моя точка останова 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;
}
В частности, метаданные . hasAnnotatedMethods ()
вызывает getDeclaredMethods ()
для класса, который загружает все классы параметров всех методов этого класса. Я предполагаю, что это, возможно, не конец проблемы, потому что я думаю, что классы должны быть выгружены. Может ли JVM кэшировать экземпляр класса по непонятным причинам?
Вариант 1) Аспект J с открытым исходным кодом.Вскройте его и посмотрите, что происходит.
Вариант 2) Переименуйте свой класс в Bang, посмотрите, заработает ли он.
Я не удивлюсь, если там есть жесткое кодирование для пропуска "lang", хотя я не могу сказать, почему.
Изменить -
Вижу такой код в исходниках
if (superclassnameIndex > 0) { // May be zero -> class is java.lang.Object
superclassname = cpool.getConstantString(superclassnameIndex, Constants.CONSTANT_Class);
superclassname = Utility.compactClassName(superclassname, false);
} else {
superclassname = "java.lang.Object";
}
Похоже, они пытаются пропустить вплетение java.lang.stuff.... не вижу ничего для просто "lang", но он может быть там (или ошибка)