运行AspectJ的原因的NoSuchMethodError:Aspect.aspectOf原因、AspectJ、NoSuchMethodError、aspectOf

2023-09-06 13:55:29 作者:老痞子.

我有一个非常简单的AspectJ方面(使用@AspectJ)刚刚打印出的日志信息。我的目标是劝告code在我的Andr​​oid应用程序。现在这方面的工作完全正常,只要我有纵横类本身在我的应用程序源码 - code。 有一次,我将纵横成不同的模块(无论是爪哇 - >的.jar或Android LIB - > .aar)我得到以下运行时异常运行谏code在我的应用程序时:

I have a very simple AspectJ aspect (using @AspectJ) which just prints out a log message. My goal is to advice code in my android application. Now this aspects works perfectly fine as long as I have the aspect class itself in my applications source-code. Once I move the aspect into a different module (either java -> .jar or android lib -> .aar) I get the following runtime exception when running the adviced code in my application:

java.lang.NoSuchMethodError: com.xxx.xxx.TraceAspect.aspectOf

基本上我的结构是这样的:

Basically my structure is like this:

Root
 + app (com.android.application)
   - MainActivity (with annotation to be adviced)
 + library (android-library)
   - TraceAspect (aspect definition)

从AJC编译器,我可以看到,AJC编译拿起我的课,正确通知:他们,所以我真的不知道为什么它的工作原理,只要我有@AspectJ类在我的源$ C ​​$ C ,但停止工作,一旦我将它移动到一个JAR档案。

From the ajc compiler, I can see that the ajc compiler picks up my classes and advices them correctly, so I really don't know why it works as long as I have the @AspectJ class in my sourcecode, but stops working once I move it to a jar archive.

我使用的摇篮。 Buildscript我的应用程序是非常简单的。我也跟着在http://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/

I am using gradle. Buildscript for my app is super simple. I followed the instructions in http://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/

import com.android.build.gradle.LibraryPlugin
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:0.12.+'
    classpath 'org.aspectj:aspectjtools:1.8.1'
  }
}

apply plugin: 'com.android.application'

repositories {
  mavenCentral()
}

dependencies {
  compile 'org.aspectj:aspectjrt:1.8.1'
  compile project (':library')
}


android.applicationVariants.all { variant ->
    AppPlugin plugin = project.plugins.getPlugin(AppPlugin)
    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.5",
                         "-XnoInline",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", plugin.project.android.bootClasspath.join(File.pathSeparator)]

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler)

        def log = project.logger
        for (IMessage message : handler.getMessages(null, true)) {
            switch (message.getKind()) {
                case IMessage.ABORT:
                case IMessage.ERROR:
                case IMessage.FAIL:
                    log.error message.message, message.thrown
                    break;
                case IMessage.WARNING:
                    log.warn message.message, message.thrown
                    break;
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break;
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break;
            }
        }
    }
}

不知道是否很重要,但为了以防万一,我的方面,code:

Not sure if important, but just in case, the code of my aspect:

@Aspect
public class TraceAspect {
  private static final String POINTCUT_METHOD = "execution(@com.xxx.TraceAspect * *(..))";

  @Pointcut(POINTCUT_METHOD)
  public void annotatedMethod() {}

  @Around("annotatedMethod()")
  public Object weaveJoinPoint(ProceedingJoinPoint joinPoint) throws Throwable {
    System.out.println("Aspect works...");
    return joinPoint.proceed();
  }
}

类路径

我还检查 javaCompile.classPath ,它正确地包含了库classes.jar 和我的 APP-classes.jar 。添加 -log文件 AJC 任务也表明,文件被正确地编织。

I also checked the javaCompile.classPath and it correctly contains both the library-classes.jar and my app-classes.jar. Adding -log file to the ajc tasks also shows that files are correctly weaved.

任何想法?

小例子来重现此问题

https://github.com/fschoellhammer/test-aspectj

推荐答案

我有一个摇篮AspectJ的插件发挥各地并把它应用到的注释的子项目是这样的:

I played around with a Gradle AspectJ plugin and applied it to the annotation subproject like this:

buildscript {
    repositories {
        maven {
            url "https://maven.eveoh.nl/content/repositories/releases"
        }
    }

    dependencies {
        classpath "nl.eveoh:gradle-aspectj:1.4"
    }
}

project.ext {
    aspectjVersion = '1.8.4'
}

apply plugin: 'aspectj'

project.convention.plugins.java.sourceCompatibility = org.gradle.api.JavaVersion.VERSION_1_7
project.convention.plugins.java.targetCompatibility = org.gradle.api.JavaVersion.VERSION_1_7

现在的应用作品,在仿真器和DDMS从Android SDK显示,建议输出在控制台上的预期。 : - )

Now the app works in the emulator and DDMS from the Android SDK shows that the advice output is on the console as expected. :-)

请注意,我这个项目升级到1.8.4的AspectJ和Java 7,我也改变了这些设置:

Please note that I have upgraded the project to AspectJ 1.8.4 and Java 7. I have also changed these settings:

Index: app/build.gradle
===================================================================
--- app/build.gradle    (revision 9d9c3ce4e0f903b5e7c650f231577c20585e6923)
+++ app/build.gradle    (revision )
@@ -2,8 +2,7 @@

 dependencies {
     // aspectJ compiler
-    compile 'org.aspectj:aspectjrt:1.8.1'
-
+    compile 'org.aspectj:aspectjrt:1.8.4'
     compile (project (':annotation'))
 }

@@ -50,13 +49,13 @@
     JavaCompile javaCompile = variant.javaCompile
     javaCompile.doLast {
         String[] args = ["-showWeaveInfo",
-                         "-1.5",
+                         "-1.7",
                          "-XnoInline",
                          "-inpath", javaCompile.destinationDir.toString(),
                          "-aspectpath", javaCompile.classpath.asPath,
                          "-d", javaCompile.destinationDir.toString(),
                          "-classpath", javaCompile.classpath.asPath,
-                         //"-log", "/home/flo/workspace/test-aspectj/weave.log",
+                         "-log", "weave.log",
                          "-bootclasspath", plugin.project.android.bootClasspath.join(File.pathSeparator)]

         MessageHandler handler = new MessageHandler(true);
Index: build.gradle
===================================================================
--- build.gradle    (revision 9d9c3ce4e0f903b5e7c650f231577c20585e6923)
+++ build.gradle    (revision )
@@ -5,7 +5,7 @@
     dependencies {
         classpath 'com.android.tools.build:gradle:0.12.+'
         // aspectj - http://fernandocejas.com/2014/08/03/aspect-oriented-programming-in-android/
-        classpath 'org.aspectj:aspectjtools:1.8.1'
+        classpath 'org.aspectj:aspectjtools:1.8.4'
     }
 }