是否可以将 类 包含在他们在 aop.xml 上的注释中?
Is it possible to include classes to be weaved by their annotations on aop.xml?
我正在开发一些预期会使用@AnAnnotation 进行加载时编织的方面 类。我创建了 aop.xml 如下
<!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>
根据日志,我的方面似乎尝试建议适当 类 但紧接着发生以下异常。
java.lang.NoSuchMethodError: com.example.MyAspect.aspectOf
有什么想法吗?
: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");
}
}
您的 aop.xml
中存在细微错误:
<include within="@com.example.MyAnnotation *" />
include within
规则太窄了。切面编织错误地仅限于目标 classes,切面 class 本身被排除在外,因为它本身不携带目标注释。效果是织布工
永远不会完成方面本身——记住,它不是由 AJC 编译的
前。这导致 NoSuchMethodError: ...MyAspect.aspectOf()
。因此,将编织范围扩大到整个基础包可以解决您的问题:
<include within="com.example..*" />
还有两件事你应该改进:
- 使用
@within
而不是 @target
,因为 @target
是在运行时动态计算的。只有这样我们才能确定目标实例具有哪种确切类型。 @within
然而可以在静态评估
编织.
- 使用 AspectJ 1.9.8.RC3 因为使用了 Java 17(您似乎喜欢新的文本块)。对于 LTW,只要字节码兼容,这可能不是绝对必要的,但最近尝试编译 Java 17 代码时,AspectJ 1.9.7 是不够的,因为它
最多只支持 Java 15.
这是我的 pull request 以及三个相应的提交。
更新: 如果出于任何原因你想避免在 aop.xml
中提及目标包,只需提及注释和方面,如下所示:
<!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>
一种避免显式包含方面的方法是使用 AspectJ 编译器 AJC(例如通过 AspectJ Maven 插件)简单地编译方面库。
更新 2, 关于您的后续问题:如 AspectJ 1.9.7 release notes 中所述,由于 JEP 396,您需要将 --add-opens java.base/java.lang=ALL-UNNAMED
添加到您的Java 命令行。
我在 pull request #2 中解决了你的问题。
我正在开发一些预期会使用@AnAnnotation 进行加载时编织的方面 类。我创建了 aop.xml 如下
<!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>
根据日志,我的方面似乎尝试建议适当 类 但紧接着发生以下异常。
java.lang.NoSuchMethodError: com.example.MyAspect.aspectOf
有什么想法吗?
: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");
}
}
您的 aop.xml
中存在细微错误:
<include within="@com.example.MyAnnotation *" />
include within
规则太窄了。切面编织错误地仅限于目标 classes,切面 class 本身被排除在外,因为它本身不携带目标注释。效果是织布工
永远不会完成方面本身——记住,它不是由 AJC 编译的
前。这导致 NoSuchMethodError: ...MyAspect.aspectOf()
。因此,将编织范围扩大到整个基础包可以解决您的问题:
<include within="com.example..*" />
还有两件事你应该改进:
- 使用
@within
而不是@target
,因为@target
是在运行时动态计算的。只有这样我们才能确定目标实例具有哪种确切类型。@within
然而可以在静态评估 编织. - 使用 AspectJ 1.9.8.RC3 因为使用了 Java 17(您似乎喜欢新的文本块)。对于 LTW,只要字节码兼容,这可能不是绝对必要的,但最近尝试编译 Java 17 代码时,AspectJ 1.9.7 是不够的,因为它 最多只支持 Java 15.
这是我的 pull request 以及三个相应的提交。
更新: 如果出于任何原因你想避免在 aop.xml
中提及目标包,只需提及注释和方面,如下所示:
<!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>
一种避免显式包含方面的方法是使用 AspectJ 编译器 AJC(例如通过 AspectJ Maven 插件)简单地编译方面库。
更新 2, 关于您的后续问题:如 AspectJ 1.9.7 release notes 中所述,由于 JEP 396,您需要将 --add-opens java.base/java.lang=ALL-UNNAMED
添加到您的Java 命令行。
我在 pull request #2 中解决了你的问题。