AspectJ配置/环境搭建问题:Pointcut无法触发
我正在尝试运行第一个AspectJ切面,已按照文档完成配置,参考包括:
- 开发者站点
- 搭建指南
- 连接点示例
但无论尝试何种配置选项,切面始终无法触发。之前修改Pointcut时会收到“Pointcut未被使用”的错误,现在不再出现,不清楚原因。请问问题出在配置还是Pointcut上?该如何调试这类问题?是否遗漏了文档中的某些内容?
POM配置
<packaging>jar</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <!-- <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.13.2-SNAPSHOT</version> --> <executions> <execution> <goals> <goal>compile</goal> <!-- use this goal to weave all your main classes --> <goal>test-compile</goal> <!-- use this goal to weave all your test classes --> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.7</version> </dependency> </dependencies> <configuration> <showWeaveInfo>true</showWeaveInfo> <forceAjcCompile>true</forceAjcCompile> <sources/> <weaveDirectories> <weaveDirectory>${project.build.directory}/classes</weaveDirectory> </weaveDirectories> <complianceLevel>11</complianceLevel> <source>11</source> <target>11</target> <verbose>true</verbose> <Xlint>warning</Xlint> </configuration> </plugin> </plugins> </build> <dependencies> ..... <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>RELEASE</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-launcher</artifactId> <version>1.6.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.6.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-params</artifactId> <version>5.6.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.jetbrains</groupId> <artifactId>annotations</artifactId> <version>22.0.0</version> </dependency> <!-- https://mvnrepository.com/artifact/dev.aspectj/aspectj-maven-plugin --> <dependency> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.13.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjrt --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.7</version> <scope>runtime</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.7</version> <scope>runtime</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.7</version> </dependency> </dependencies>
切面代码
public aspect MdDOMAINChildAspect { pointcut myExceptionHandlerPointcut(): execution(void mdDOMAIN.MdDOMAINInstance.testCall() ); before(): myExceptionHandlerPointcut() { System.out.println("-------------- Aspect Advice Logic ---------------"); } }
目标类代码
@Data public class MdDOMAINInstance { @MdDOMAINChildAnnotation(selectName = "Indicators") public MdDOMAINInstance selectFilingIndicators() throws NoSuchMethodException { testCall(); Method m=this.getClass().getMethod("selectFilingIndicators"); MdDOMAINChildAnnotation metaidAnnotation=m.getAnnotation(MdDOMAINChildAnnotation.class); System.out.println("Annotation: " + metaidAnnotation.selectName()); return this; } public void testCall() { System.out.println("In testCall()"); return ; } }
测试类代码
class MdDOMAINInstanceTest { @Test void selectFilingIndicatorsTest() throws NoSuchMethodException { MdDOMAINInstance mdDOMAINInstance = new MdDOMAINInstance().selectFilingIndicators(); } }
Maven测试命令
clean test -Dtest=MdDOMAINInstanceTest -f pom.xml
Maven测试运行结果
"C:\Program Files\Java\jdk-11.0.12\bin\java.exe" -Dmaven.multiModuleProjectDirectory=....IdeaProjects\us-MYROOT-DOMAIN-004 "-Dmaven.home=C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\plugins\maven\lib\maven3" "-Dclassworlds.conf=C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\plugins\maven\lib\maven3\bin\m2.conf" "-Dmaven.ext.class.path=C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\plugins\maven\lib\maven-event-listener.jar" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar=52349:C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\plugins\maven\lib\maven3\boot\plexus-classworlds-2.6.0.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.1\plugins\maven\lib\maven3\boot\plexus-classworlds.license" org.codehaus.classworlds.Launcher -Didea.version=2021.3.2 clean test -Dtest=MdDOMAINInstanceTest [INFO] Scanning for projects... [WARNING] [WARNING] Some problems were encountered while building the effective model for us-MYROOT:us-MYROOT-DOMAIN-004:jar:1.0-SNAPSHOT [WARNING] 'dependencies.dependency.version' for org.junit.jupiter:junit-jupiter:jar is either LATEST or RELEASE (both of them are being deprecated) @ line 117, column 22 [WARNING] 'build.plugins.plugin.version' for org.apache.maven.plugins:maven-compiler-plugin is missing. @ line 20, column 21 [WARNING] [WARNING] It is highly recommended to fix these problems because they threaten the stability of your build. [WARNING] [WARNING] For this reason, future Maven versions might no longer support building such malformed projects. [WARNING] [INFO] [INFO] --------------< us-MYROOT:us-MYROOT-DOMAIN-004 >-------------- [INFO] Building us-MYROOT-DOMAIN-004 1.0-SNAPSHOT [INFO] --------------------------------[ jar ]--------------------------------- [INFO] [INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ us-MYROOT-DOMAIN-004 --- [INFO] Deleting .....IdeaProjects\us-MYROOT-DOMAIN-004\target [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ us-MYROOT-DOMAIN-004 --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ us-MYROOT-DOMAIN-004 --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 3 source files to .....IdeaProjects\us-MYROOT-DOMAIN-004\target\classes [INFO] [INFO] --- aspectj-maven-plugin:1.14.0:compile (default) @ us-MYROOT-DOMAIN-004 --- [INFO] Showing AJC message detail for messages of types: [error, warning, fail] [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ us-MYROOT-DOMAIN-004 --- [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] Copying 0 resource [INFO] [INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ us-MYROOT-DOMAIN-004 --- [INFO] Changes detected - recompiling the module! [INFO] Compiling 1 source file to .....IdeaProjects\us-MYROOT-DOMAIN-004\target\test-classes [INFO] [INFO] --- aspectj-maven-plugin:1.14.0:test-compile (default) @ us-MYROOT-DOMAIN-004 --- [INFO] Showing AJC message detail for messages of types: [error, warning, fail] [WARNING] You aren't using a compiler supported by lombok, so lombok will not work and has been disabled. Your processor is: org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.BatchProcessingEnvImpl Lombok supports: OpenJDK javac, ECJ <unknown source file>:<no line information> [INFO] [INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ us-MYROOT-DOMAIN-004 --- [INFO] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running mdDOMAIN.MdDOMAINInstanceTest In testCall() Annotation: Indicators [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.065 s - in mdDOMAIN.MdDOMAINInstanceTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 22.238 s [INFO] Finished at: 2022-10-21T20:14:46+11:00 [INFO] ------------------------------------------------------------------------ Process finished with exit code 0
核心问题:切面未被编译与织入
从Maven日志可以看到,aspectj-maven-plugin:1.14.0:compile阶段没有输出任何织入信息(showWeaveInfo=true却无内容),说明AJC(AspectJ编译器)根本没有处理你的切面类,也没有对目标类进行织入操作。主要原因有两个:
切面类未被AJC编译
你的aspectj-maven-plugin配置中设置了<sources/>空标签,这会阻止AJC读取项目的源码目录,导致切面类(.java格式的AspectJ切面)无法被编译成可执行的字节码。同时,maven-compiler-plugin先于AJC执行,它无法识别AspectJ语法,所以切面类虽然被javac编译,但实际上是无效的(因为普通Java编译器不认识aspect、pointcut等关键字)。织入时机错误
配置中的<weaveDirectories>指向已经编译好的类目录,但此时目标类已经被javac编译完成,AJC只能尝试后织入,但由于切面本身未被正确编译,无法完成织入逻辑。
修复步骤
1. 修正AspectJ Maven插件配置
移除<sources/>标签,让AJC自动读取项目的主源码目录,同时让AJC负责编译所有主源码(包括切面和普通Java类),而不是先javac编译再织入。修改后的插件配置如下:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <executions> <execution> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.7</version> </dependency> </dependencies> <configuration> <showWeaveInfo>true</showWeaveInfo> <forceAjcCompile>true</forceAjcCompile> <!-- 移除空的<sources/>标签 --> <!-- <sources/> --> <!-- 移除weaveDirectories,让AJC直接编译源码并织入 --> <!-- <weaveDirectories> <weaveDirectory>${project.build.directory}/classes</weaveDirectory> </weaveDirectories> --> <complianceLevel>11</complianceLevel> <source>11</source> <target>11</target> <verbose>true</verbose> <Xlint>warning</Xlint> </configuration> </plugin>
2. 调整Maven编译插件执行顺序(可选但推荐)
为了确保AJC优先于javac执行,可以给aspectj-maven-plugin的compile执行阶段设置phase为process-sources,或者禁用maven-compiler-plugin的默认compile执行:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <!-- 补充缺失的版本号 --> <configuration> <source>11</source> <target>11</target> </configuration> <!-- 禁用默认编译执行,由AJC负责编译 --> <executions> <execution> <id>default-compile</id> <phase>none</phase> </execution> <execution> <id>default-testCompile</id> <phase>none</phase> </execution> </executions> </plugin>
3. 清理不必要的依赖
移除dev.aspectj:aspectj-maven-plugin依赖,因为这是Maven插件,不是项目依赖,不需要放在<dependencies>中:
<!-- 移除以下依赖 --> <!-- <dependency> <groupId>dev.aspectj</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.13.1</version> </dependency> -->

