Ejecutar AspectJ causa NoSuchMethodError: Aspect.aspectOf
Tengo un aspecto muy simple de AspectJ (usando @AspectJ) que apenas imprime hacia fuera un mensaje del registro. Mi objetivo es el código de consejos en mi aplicación Android. Ahora, este aspecto funciona perfectamente, siempre y cuando tenga la clase de aspecto en mis aplicaciones código fuente. Una vez que muevo el aspecto en un módulo diferente (ya sea java -> .jar o android lib -> .aar) Tengo la siguiente excepción de tiempo de ejecución al ejecutar el código adviced en mi aplicación:
java.lang.NoSuchMethodError: com.xxx.xxx.TraceAspect.aspectOf
Básicamente mi estructura es así:
- Android.util.Pair mantiene String como parámetros en androidTest pero nulo en (unidad) prueba
- HttpURLConnection setConnectTimeout () no tiene ningún efecto
- Renombrar nombre del paquete jar
- Androide. Cambio de brillo
- Cómo comparar una cadena de Intent.getStringExtra ()?
Root + app (com.android.application) - MainActivity (with annotation to be adviced) + library (android-library) - TraceAspect (aspect definition)
Desde el compilador ajc, puedo ver que el compilador ajc recoge mis clases y los advierte correctamente, así que realmente no sé por qué funciona, siempre y cuando tenga la clase @AspectJ en mi código fuente, pero deja de funcionar una vez que me muevo A un archivo jar.
Estoy usando gradle. Buildscript para mi aplicación es muy simple. Seguí las instrucciones en 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; } } } }
No estoy seguro si es importante, pero por si acaso, el código de mi aspecto:
@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(); } }
Camino de clase
También he comprobado javaCompile.classPath
y contiene correctamente tanto la library-classes.jar
como mi app-classes.jar
. La adición de -log file
a las tareas de ajc
también muestra que los archivos se tejen correctamente.
¿Algunas ideas?
Ejemplo mínimo para reproducir este problema
Https://github.com/fschoellhammer/test-aspectj
- android uso pcap biblioteca
- Socket Android + ObjectOutputStream no funciona correctamente
- Es posible detener un subproceso que se está conectando a URL con httpConnection.connect ()?
- En Java, ¿cómo verifica si una variable float es null?
- ¿Hay una manera de mostrar los números primero en el teclado virtual para Android?
- Establecer el ancho del botón en Android
- La mejor manera de recuperar / formatear datos mediante Firebase Java API
- Usar putExtra para pasar valores al servicio de intenciones
Jugué con un plugin Gradle AspectJ y lo apliqué al subproyecto de anotación como este:
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
Ahora la aplicación funciona en el emulador y DDMS del SDK de Android muestra que la salida de asesoramiento está en la consola como se esperaba. :-)
Tenga en cuenta que he actualizado el proyecto a AspectJ 1.8.4 y Java 7. También he cambiado esta configuración:
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' } }
El mensaje implica que el archivo de aspecto no ha pasado por el aspectj
tejedor. El tejedor sería responsable de agregar el método aspectOf()
. Aunque sus aspectos de estilo de anotación se compilarán bien con javac
, deben ser "terminados" por aspectj
en algún momento para introducir los métodos de infraestructura que soportan el tejido. Si usted fue el tiempo de carga de tejer esto se hace como los aspectos se cargan, pero si se compila tiempo o post-compilar el tiempo de tejer, entonces usted necesita para obtener a ajc
alguna otra manera. Si tiene una biblioteca construida de esta manera:
javac MyAspect.java jar -cvMf code.jar MyAspect.class
Entonces usted necesitaría conseguir ese frasco tejido para "completar" los aspectos:
ajc -inpath code.jar -outjar myfinishedcode.jar
O simplemente puede usar ajc
lugar de javac
para el paso inicial
ajc MyAspect.java
O usted podría hacerlo en el punto que los aspectos se están aplicando a su otro código:
ajc <myAppSourceFiles> -inpath myaspects.jar
Al incluir myaspects.jar en la vía de inpath
, cualquier clase de aspecto en la que se habrá "terminado" como parte de este paso de compilación y las versiones terminadas puestas junto a los archivos de origen de la aplicación compilada. Tenga en cuenta que esto es diferente si usó la ruta de aspecto:
ajc <myAppSourceFiles> -aspectpath myaspects.jar
Aquí los aspectos de la ruta de aspecto se aplican a su código, pero sólo se cargan desde allí, no se terminan y por lo que no obtendrá las versiones terminadas junto con los archivos de origen de la aplicación compilada.
Me encuentro con el mismo problema, pero he utilizado Maven en lugar de Gradle.
Antes de que se pueda aplicar una clase de aspecto a una clase de destino, primero hay que "tejerla" en un aspecto. Una clase de aspecto tejida tendrá dos métodos estáticos agregados (aspectOf y hasAspect).
En mi caso particular no tejí mis aspectos.
Se puede hacer agregando el aspectoj-maven-plugin a la sección de compilación.
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <executions> <execution> <goals> <goal>compile</goal> </goals> </execution> </executions> </plugin> </plugins>
¡Espero eso ayude!
- Diseño deslizante como google maps v7
- ¿Es posible permitir al usuario la selección múltiple de archivos en el marco de acceso de almacenamiento ..?