У меня проблема с моим классом аспектов, когда я обманываю свои коды с помощью proguard.
У меня есть аспект, который обнаруживает все методы с аннотацией @Cacheable.
Вот пример класса, который содержит аннотацию @Cacheable
package com.mycompany.user;
public class User {
@Cacheable(scope="session", uniqueName="userInfo")
public UserInfo getUserInfo(Long userId) {
...
}
}
и вот мой код аспекта:
@Aspect
public class CacheMethodResultAspect {
@Around(
value = "execution(@com.mycompany.cache.Cacheable * *.*(..))",
argNames = "proceedingJoinPoint,joinPointStaticPart"
)
public Object retrieveResultFromCache(ProceedingJoinPoint proceedingJoinPoint, JoinPoint.StaticPart joinPointStaticPart)
throws Throwable {
final CacheScope cacheScope = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod().getAnnotation(Cacheable.class).scope();
final CacheConstants uniqueName = ((MethodSignature) proceedingJoinPoint.getSignature()).getMethod().getAnnotation(Cacheable.class).uniqueName();
final String methodLine = proceedingJoinPoint.getSignature().getDeclaringTypeName() + "." + proceedingJoinPoint.getSignature().getName()
+ "@" + joinPointStaticPart.getSourceLocation().getLine();
.
.
.
}
}
когда я регистрирую результат continueJoinPoint, он возвращает следующую строку:
execution(UserInfo java.lang.ClassNotFoundException.getUserInfo())
Я ожидаю, что он вернет этот результат:
execution(UserInfo com.mycompany.user.getUserInfo())
он определяет только имя метода! поэтому я не могу получить аннотацию @Cacheable для этого метода!
я не хочу использовать:
-keep class myClassName...
Аспектная версия: 1.6.12
версия java: 1.7 обновление 21
версия для proguard: 4.9
любая помощь будет оценена.
Хорошо, это было очень сложно, но, наконец, я смог воспроизвести проблему с неправильной MethodSignature
хранящейся в этом thisJoinPointStaticPart
. Я попробовал много опций ProGuard, но, наконец, я обнаружил, что -adaptclassstrings
был недостающим. Очевидно, что AspectJ использует имена классов, закодированные в строках - возможно, что-то похожее на Class.forName()
, я не проверял код байта.
Самая важная часть конфигурации ProGuard Maven Plugin:
<configuration>
<options>
<option>-target 1.7</option>
<option>-adaptclassstrings</option>
<option>-keepclasseswithmembers public class * { public static void main(java.lang.String[]); }</option>
<option>-keepattributes *Annotation*</option>
<option>-keepclassmembernames class * { @de.scrum_master.app.Cacheable *** **(...); }</option>
</options>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
<!--<lib>${java.home}/lib/jsse.jar</lib>-->
</libs>
</configuration>
Поскольку полное объяснение слишком велико, чтобы процитировать здесь полный код образца и т.д., Я создал для вас проект GitHub. Пожалуйста, проверьте код и настройки Maven для ProGuard. Вы можете просто клонировать репозиторий и звонить
mvn install
Я сделал это очень удобно для вас, я даже включил шаг сборки OneJAR, поэтому после сборки вы можете просто позвонить
java -jar target/aspectj-proguard-1.0-SNAPSHOT.one-jar.jar
из каталога проекта. Результат должен выглядеть следующим образом:
User{id=1, info=UserInfo{info='First'}}
User{id=2, info=UserInfo{info='Second'}}
User{id=3, info=UserInfo{info='Third'}}
User{id=4, info=UserInfo{info='Fourth'}}
User{id=5, info=UserInfo{info='Fifth'}}
execution(d de.scrum_master.app.b.getUserInfo(Long))
Cacheable scope: session
Cacheable unique name: userInfo
Method line: de.scrum_master.app.b.getUserInfo@27
UserInfo{info='First'}
execution(d de.scrum_master.app.b.getUserInfo(Long))
Cacheable scope: session
Cacheable unique name: userInfo
Method line: de.scrum_master.app.b.getUserInfo@27
UserInfo{info='Third'}
execution(d de.scrum_master.app.b.getUserInfo(Long))
Cacheable scope: session
Cacheable unique name: userInfo
Method line: de.scrum_master.app.b.getUserInfo@27
UserInfo{info='Fifth'}
execution(d de.scrum_master.app.b.getUserInfo(Long))
Cacheable scope: session
Cacheable unique name: userInfo
Method line: de.scrum_master.app.b.getUserInfo@27
null
Дополнительные подсказки:
Наслаждайтесь! Надеюсь, это решит вашу проблему. :-)
Обновление: я забыл упомянуть, как точно воспроизвести проблему: просто удалите <option>-adaptclassstrings</option>
, перестройте и снова запустите программу:
(...)
User{id=5, info=UserInfo{info='Fifth'}}
execution(ClassNotFoundException java.lang.ClassNotFoundException.getUserInfo(Long))
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.simontuffs.onejar.Boot.run(Boot.java:306)
at com.simontuffs.onejar.Boot.main(Boot.java:159)
Caused by: java.lang.NullPointerException
at de.scrum_master.a.a.a(Unknown Source)
at de.scrum_master.app.b.getUserInfo(Unknown Source)
at de.scrum_master.app.Application.main(Unknown Source)
... 6 more