自定义AspectJ切面与maven-surefire-plugin配合运行失败排查
核心原因分析
aspectOf()是AspectJ为单例切面自动生成的方法,报错说明JVM找不到这个方法,本质是切面类没被AspectJ正确织入,或者测试时类加载器没拿到织入后的类。主项目和独立测试项目的差异,大概率是Maven插件执行顺序、类路径冲突、或Surefire与AspectJ的织入逻辑不兼容导致。
逐步排查步骤
调整aspectj-maven-plugin的执行时机
必须让切面织入操作在测试执行前完成,确保aspectj-maven-plugin在surefire-plugin之前执行,或者明确指定其执行阶段为process-test-classes:<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <executions> <execution> <phase>process-test-classes</phase> <!-- 测试类编译后、测试执行前执行 --> <goals> <goal>test-compile</goal> <!-- 织入测试类与切面 --> <goal>compile</goal> <!-- 织入主项目类 --> </goals> </execution> </executions> <configuration> <complianceLevel>11</complianceLevel> <!-- 匹配你的JDK版本 --> <source>11</source> <target>11</target> </configuration> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.7</version> <!-- 和aspectjrt版本保持一致 --> </dependency> </dependencies> </plugin>避免织入方式冲突
你之前给Surefire配置了AspectJ运行时织入代理,同时又用aspectj-maven-plugin做编译时织入,两种方式混用容易引发类加载冲突,建议二选一:- 保留编译时织入:删除Surefire配置中
argLine里的-javaagent:aspectjweaver.jar,因为编译阶段已经完成织入,不需要运行时代理。 - 保留运行时织入:移除aspectj-maven-plugin的
compile和test-compile执行目标,确保aspectjweaver依赖在测试类路径中,且切面类能被正确扫描。
- 保留编译时织入:删除Surefire配置中
检查切面类的可见性
确保utils.Aspects类满足:- 标注了
@Aspect注解(导入org.aspectj.lang.annotation.Aspect) - 是public权限(Kotlin默认是internal,可能导致测试类加载不到)
- 切点表达式正确,比如拦截主项目类时,要保证主项目类已被编译并纳入织入范围
- 标注了
清理依赖冲突
用mvn dependency:tree查看依赖树,确保aspectjrt、aspectjweaver、aspectjtools的版本完全一致,排除重复或版本不一致的AspectJ依赖。调整Surefire的fork模式
Surefire的fork模式可能导致类加载异常,尝试关闭fork或指定fork模式:<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M7</version> <configuration> <forkCount>0</forkCount> <!-- 关闭fork测试类加载是否正常 --> </configuration> </plugin>
验证方法
修改配置后,先执行mvn clean process-test-classes,然后用反编译工具查看target/test-classes和target/classes下的class文件,确认切面类包含aspectOf()方法(织入成功的标志),再运行mvn test验证。
内容的提问来源于stack exchange,提问作者mikamika

