使用aspectj-maven-plugin与AspectJ实现日志拦截遇问题求助
问题分析与解决方案
1. 思路是否有误?
是的,你的核心思路存在两个关键偏差:
- ProjectA定位错误:你将ProjectA做成了提前完成织入的Jar,但实际上你需要的是纯切面类Jar(仅包含AspectJ切面代码,不提前织入第三方依赖),因为你的目标是在ProjectB编译阶段动态织入,以此规避版本冲突。
- weaveDependencies使用场景错误:在ProjectA中配置
weaveDependencies为logback-classic,会导致ProjectA打包时就将织入切面后的logback-classic类打进Jar,这不仅引入冗余代码,还会和ProjectB自身的logback版本冲突,完全违背了「在ProjectB端织入」的初衷。
2. 失败原因及正确实现方式
失败原因
- ProjectA打包时已将织入后的logback-classic类封装进Jar,而ProjectB配置
aspectLibrary引用ProjectA时,AspectJ只会用ProjectA的切面去织入ProjectB自身的类,不会覆盖ProjectB独立引入的logback-classic依赖,导致织入效果不可见。 - ProjectA中提前织入的logback类会与ProjectB的logback依赖产生版本冲突,进一步导致织入逻辑失效。
正确实现方式
步骤1:重构ProjectA模块设计
每个功能模块(如logback-module、mysql-module)仅保留纯AspectJ切面代码,不提前织入任何第三方依赖:
- 移除模块中
aspectj-maven-plugin的weaveDependencies配置,仅保留编译切面类的基础配置:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <executions> <execution> <goals> <goal>compile</goal> <!-- 仅编译切面类,不织入第三方依赖 --> </goals> </execution> </executions> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.9.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.9.1</version> </dependency> </dependencies> <configuration> <source>1.8</source> <!-- 匹配你的JDK版本 --> <target>1.8</target> <complianceLevel>1.8</complianceLevel> </configuration> </plugin>
- 模块依赖仅保留API级别依赖,例如logback-module引入
logback-classic时使用providedscope(避免打包时引入):
<dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.11</version> <scope>provided</scope> </dependency>
步骤2:ProjectB端配置AspectJ织入逻辑
在ProjectB的pom.xml中,配置aspectj-maven-plugin,将ProjectA的对应模块(如logback-module)设为aspectLibraries,并指定需要织入的目标依赖:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.14.0</version> <executions> <execution> <id>compile-with-aspectj</id> <goals> <goal>compile</goal> <goal>test-compile</goal> </goals> <configuration> <aspectLibraries> <aspectLibrary> <groupId>your.group.id</groupId> <artifactId>projectA-logback-module</artifactId> </aspectLibrary> </aspectLibraries> <!-- 指定需要织入的第三方依赖 --> <weaveDependencies> <weaveDependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> </weaveDependency> </weaveDependencies> </configuration> </execution> </executions> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.9.1</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>1.9.9.1</version> </dependency> </dependencies> </plugin>
- 引入ProjectA模块时使用
compilescope,确保切面类能被AspectJ工具识别:
<dependency> <groupId>your.group.id</groupId> <artifactId>projectA-logback-module</artifactId> <version>your-version</version> </dependency>
步骤3:解决开发环境运行问题
SpringBoot开发环境直接运行主类时,默认不会触发AspectJ的编译时织入(CTW),需添加以下配置:
- 在
src/main/resources/META-INF/aop.xml中声明切面类:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver> <!-- 织入logback的类 --> <include within="ch.qos.logback.classic..*"/> <!-- 织入业务类(按需配置) --> <include within="your.projectB.package..*"/> </weaver> <aspects> <!-- 声明ProjectA中的切面类 --> <aspect name="your.projectA.logback.aspect.LogbackInterceptorAspect"/> </aspects> </aspectj>
- 添加AspectJ代理依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
此时开发环境运行时,Spring AOP会结合AspectJ的加载时织入(LTW)完成切面织入,避免版本冲突。
关键注意事项
- 版本隔离:ProjectA的多版本模块(如mysql-module-8.0/5.7)仅保留对应版本的API依赖(provided scope),ProjectB根据自身依赖版本选择对应的ProjectA模块,实现版本适配。
- 禁止提前织入:所有织入逻辑必须在使用方(ProjectB)完成,绝对不要在ProjectA中对第三方依赖进行织入操作,确保依赖版本由使用方完全控制。
内容的提问来源于stack exchange,提问作者Kim
相关产品推荐
相关产品推荐

