当我用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();
.
.
.
}
}
当我记录proceedingJoinPoint的结果时,它返回以下行:
execution(UserInfo java.lang.ClassNotFoundException.getUserInfo())
我希望它会返回此结果:
execution(UserInfo com.mycompany.user.getUserInfo())
它只检测方法名称!所以我无法获取此方法的@Cacheable注释!
我不想使用:
-keep class myClassName...
aspectj version:1.6.12
java版:1.7 update 21
proguard版本:4.9
任何帮助将不胜感激。
答案 0 :(得分:3)
好的,这非常棘手,但最后我能够使用MethodSignature
中存储的错误thisJoinPointStaticPart
重现问题。我尝试了很多ProGuard选项,但最后我发现-adaptclassstrings
是缺失的选项。显然,AspectJ使用在字符串中编码的类名 - 可能类似于Class.forName()
,我没有检查字节代码。
ProGuard Maven插件配置中最重要的部分是:
<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 project 。请检查ProGuard的代码和Maven设置。您只需克隆存储库并调用
即可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