Reputation: 53
I'm developing some aspects which are expected to load-time weave classes with @AnAnnotation. I created aop.xml as follows
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-verbose -showWeaveInfo">
<include within="@com.example.MyAnnotation *" />
</weaver>
<aspects>
<aspect name="com.example.MyAspect" />
</aspects>
</aspectj>
and according to log, my aspect seems to try advise appropriate classes but right after that the following exception occurred.
java.lang.NoSuchMethodError: com.example.MyAspect.aspectOf
Any ideas?
:log
[ERROR] [AppClassLoader@2b193f2d] info AspectJ Weaver Version 1.9.7 built on Thursday Jun 24, 2021 at 16:14:45 PDT
[ERROR] [AppClassLoader@2b193f2d] info register classloader jdk.internal.loader.ClassLoaders$AppClassLoader@2b193f2d
[ERROR] [AppClassLoader@2b193f2d] info using configuration project/target/classes/META-INF/aop.xml
[ERROR] [AppClassLoader@2b193f2d] info register aspect com.example.MyAspect
[ERROR] [AppClassLoader@2b193f2d] weaveinfo Join point 'constructor-execution(void com.example.MyAspectTest$MyTargetClass.<init>(com.example.MyAspectTest, java.lang.String))' in Type 'com.example.MyAspectTest$MyTargetClass' (MyAspectTest.java:165) advised by afterReturning advice from 'com.example.MyAspect' (MyAspect.java) [with runtime test]
[ERROR] [AppClassLoader@2b193f2d] weaveinfo Join point 'method-execution(void com.example.MyAspectTest$MyTargetClass.myMethod(int))' in Type 'com.example.MyAspectTest$MyTargetClass.' (MyAspectTest.java:182) advised by afterReturning advice from 'com.example.MyAspect' (MyAspect.java) [with runtime test]
[INFO] Running com.example.MyAspectTest
[ERROR] Tests run: 5, Failures: 0, Errors: 5, Skipped: 0, Time elapsed: 0.055 s <<< FAILURE! - in com.example.MyAspectTest
[ERROR] com.example.MyAspectTest.testMyMethod Time elapsed: 0.011 s <<< ERROR!
java.lang.NoSuchMethodError: 'com.example.MyAspect com.example.MyAspect.aspectOf()'
at com.example.MyAspectTest.<init>(MyAspectTest.java:57)
:MyAspect.java
package com.example;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class MyAspect {
@AfterReturning("""
@target(com.example.MyAnnotation)
&& (execution(* *.*(..)) || execution(* .new(..)))
""")
public void intercept(JoinPoint JoinPoint) throws Throwable {
System.out.println("********** MyAspect intercepted");
}
}
Upvotes: 0
Views: 945
Reputation: 67317
There is a subtle error in your aop.xml
:
<include within="@com.example.MyAnnotation *" />
The include within
rule is too narrow. Aspect weaving is falsely limited to only target classes, the aspect class itself is excluded, because it does not carry the target annotation itself. The effect is that the weaver
never finishes the aspect itself - remember, it was not compiled by AJC
before. This caused NoSuchMethodError: ...MyAspect.aspectOf()
. So widening the weaving scope to the whole base package fixes your problem:
<include within="com.example..*" />
Two more things you should improve:
@within
rather than @target
, because @target
is evaluated dynamically during runtime. Only then we know for certain which exact type a target instance has. @within
however can be evaluated statically during
weaving.Here is my pull request with the three corresponding commits.
Update: If for whatever reason you want to avoid mentioning the target package in aop.xml
, simply just mention the annotation and the aspect like this:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver options="-verbose -showWeaveInfo">
<include within="com.example.MyAspect"/>
<include within="@com.example.MyAnnotation *"/>
</weaver>
<aspects>
<aspect name="com.example.MyAspect"/>
</aspects>
</aspectj>
A way to avoid explicitly including the aspect is to simply compile the aspect library with the AspectJ Compiler AJC (e.g. via AspectJ Maven Plugin).
Update 2, regarding your follow-up question: As described in the AspectJ 1.9.7 release notes, due to JEP 396 you need to add --add-opens java.base/java.lang=ALL-UNNAMED
to your Java command line.
I fixed your problem in pull request #2.
Upvotes: 1