L'esecuzione di AspectJ causa NoSuchMethodError: Aspect.aspectOf

Ho un aspetto AspectJ molto semplice (utilizzando @AspectJ) che printing appena un messaggio di registro. Il mio objective è quello di consigliare il codice nella mia applicazione android. Ora questi aspetti funzionano perfettamente finché ho la class di aspetto nelle mie applicazioni codice sorgente. Una volta spostato l'aspetto in un module diverso (java -> .jar o android lib -> .ar) ho l'exception di runtime che segue durante l'esecuzione del codice consigliato nella mia applicazione:

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

Fondamentalmente la mia struttura è così:

  • Android ha ritardato i clic in ListView
  • Identificare se il punto è nel poligono
  • Cassetto di navigazione Android sulle tabs
  • Android: Numero di tracce degli oggetti creati
  • Android - Maneggiare "Enter" in un EditText
  • Come permettere agli utenti di controllare l'ultima versione di app dall'interno dell'app?
  •  Root + app (com.android.application) - MainActivity (with annotation to be adviced) + library (android-library) - TraceAspect (aspect definition) 

    Dal compilatore di ajc, posso vedere che il compilatore ajc raccoglie le mie lezioni e le avvisa correttamente, quindi non so proprio perché funziona finché ho la class @AspectJ nel mio codice sorgente, ma smettevo di lavorare una volta che mi muovo ad un archivio di jar.

    Sto usando gradel. Buildscript per la mia applicazione è super semplice. Ho seguito le istruzioni 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; } } } } 

    Non sono sicuro se importnte, ma solo nel caso, il codice del mio aspetto:

     @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(); } } 

    classpath

    Ho anche controllato il javaCompile.classPath e contiene correttamente sia la library-classs.jar e le mie app-classs.jar . L'aggiunta di un -log file ajc task ajc mostra anche che i file sono tessuti correttamente.

    Qualche idea?

    Esempio minimo per riprodurre questo problema

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

  • Android: Distinct e GroupBy in ContentResolver
  • La lunghezza massima del metodo Intend putExtra? (Forza chiusa)
  • Utilizzando android gradle + pugnale per eseguire instrumentTests
  • GcmReceiver / GcmListenerService di Android applica l'applicazione in primo piano alla ricezione
  • La window di dialogo scompare durante il cambio di orientamento nel frammento
  • Applicazione Android per imitare una scheda RFID fisica
  • 3 Solutions collect form web for “L'esecuzione di AspectJ causa NoSuchMethodError: Aspect.aspectOf”

    Ho giocato con un plugin di Gradle AspectJ e l'ho applicata al sottoprogetto di annotazione come questo:

     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 

    Ora l'applicazione funziona nell'emulatore e DDMS dal SDK di Android mostra che l'output di consiglio è sulla console come previsto. :-)

    Registro di console del monitor Debug

    Si prega di notare che ho aggiornato il progetto a AspectJ 1.8.4 e Java 7. Ho anche modificato queste impostazioni:

     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' } } 

    Il messaggio implica che il file di aspetto non sia passato attraverso il tessitore di aspectj . Il tessitore sarebbe responsabile dell'aggiunta del metodo aspectOf() . Anche se gli aspetti della tua stile di annotazione compilano bene con javac , devono essere "finiti" da aspectj ad un certo punto per introdurre i methods di infrastruttura che supportno la tessitura. Se fossi tempo di caricamento, questo è fatto come gli aspetti sono caricati, ma se si è tempo di compilazione o tempi di post-compilazione tessitura allora è necessario portrli a ajc qualche altro modo. Se hai una libreria così costruita:

     javac MyAspect.java jar -cvMf code.jar MyAspect.class 

    allora dovreste get quel jar intessuto per "completare" gli aspetti:

     ajc -inpath code.jar -outjar myfinishedcode.jar 

    Oppure si potrebbe usare solo ajc invece di javac per il passo iniziale

     ajc MyAspect.java 

    O potresti farlo al punto in cui gli aspetti vengono applicati all'altro codice:

     ajc <myAppSourceFiles> -inpath myaspects.jar 

    Con l'inclusione di myaspects.jar inpath , tutte le classi di aspetti in esso verranno "completate" come parte di questo compilatore e le versioni terminate vengono messe insieme ai file di origine dell'applicazione compilata. Nota: questo è diverso se si utilizza il path di aspetto:

     ajc <myAppSourceFiles> -aspectpath myaspects.jar 

    Qui gli aspetti del path dell'aspetto vengono applicati al codice ma vengono caricati da lì, non vengono terminati e quindi non verranno visualizzate le versioni finite accanto ai file di origine dell'applicazione compilata.

    Corro allo stesso problema ma ho usato Maven invece di Gradle.

    Prima che una class aspetto possa essere applicata a una class target, occorre prima essere "tessuto" in un aspetto. Una class di aspetto tessuto avrà due methods statici aggiunti (aspectOf e hasAspect).

    Nel mio caso particolare non ho tessuto i miei aspetti.

    Può essere fatto aggiungendo il plugin aspectj-maven alla sezione build.

     <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> </plugins> 

    Spero che sia d'aiuto!

    L'Android è un fan Android di Google, tutto su telefoni Android, Android Wear, Android Dev e applicazioni Android Games e così via.