如何让含自定义注解与AspectJ切面的JAR在所有Maven项目中生效?
我来帮你搞定这个切面跨项目不生效的问题!其实你遇到的情况特别常见——自己项目里测试切面好好的,打包成JAR给别的非Spring项目用就失效,核心原因是AspectJ不是Java原生特性,必须通过「织入」步骤把切面代码注入到目标类里,本地测试时你的开发环境(比如IDEA)或者Maven配置已经偷偷帮你做了织入,但普通JAR包本身不会自动触发这个逻辑。
下面给你两种实用方案,按需选择:
方案一:编译时织入(CTW)—— 推荐非Spring项目用
这种方式是在引入切面的项目编译阶段,直接把切面代码织入到目标类的字节码里,优点是运行时不用额外配置,性能也更好。
第一步:先把你的切面项目打包对
在切面项目的pom.xml里加上AspectJ Maven插件,确保切面类被正确编译,并且打包后的JAR包含AspectJ织入所需的信息:
<build> <plugins> <!-- 配置AspectJ编译插件,处理切面类编译 --> <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.9.1</version> </dependency> </dependencies> <configuration> <!-- 对应你的Java 8版本 --> <source>1.8</source> <target>1.8</target> <complianceLevel>1.8</complianceLevel> <showWeaveInfo>true</showWeaveInfo> </configuration> </plugin> </plugins> </build>
执行mvn clean install把这个配置好的JAR安装到本地仓库。
第二步:在引入切面的新项目里配置织入
在新的非Spring项目的pom.xml里,需要做两件事:引入切面依赖,同时配置AspectJ插件让编译时把切面织入到当前项目的类中:
<dependencies> <!-- 引入你的切面项目依赖 --> <dependency> <groupId>你的项目groupId</groupId> <artifactId>你的切面项目artifactId</artifactId> <version>你的版本号</version> </dependency> <!-- 引入AspectJ运行时依赖 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.9.1</version> </dependency> </dependencies> <build> <plugins> <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>aspectjtools</artifactId> <version>1.9.9.1</version> </dependency> </dependencies> <configuration> <source>1.8</source> <target>1.8</target> <complianceLevel>1.8</complianceLevel> <!-- 告诉插件要织入来自切面JAR的切面逻辑 --> <weaveDependencies> <weaveDependency> <groupId>你的项目groupId</groupId> <artifactId>你的切面项目artifactId</artifactId> </weaveDependency> </weaveDependencies> </configuration> </plugin> </plugins> </build>
这样编译新项目时,AspectJ插件就会自动把切面代码织入到标注了你的自定义注解的类里,运行时切面就能正常工作了。
方案二:加载时织入(LTW)—— 无需修改引入项目的编译配置
如果不想让每个引入切面的项目都配置AspectJ插件,可以用LTW——也就是JVM加载类的时候动态织入切面。优点是引入项目不用改编译配置,缺点是启动时需要加JVM参数,性能略逊于CTW。
第一步:配置切面项目的LTW信息
先在切面项目里添加src/main/resources/META-INF/aop.xml文件,这是LTW的核心配置文件,用来告诉AspectJ哪些切面需要织入:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "https://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver> <!-- 指定要织入的包,*代表所有包,也可以写具体包名比如com.your.project..* --> <include within="*"/> </weaver> <aspects> <!-- 替换成你的切面类的全限定名 --> <aspect name="com.your.aspect.YourAspectClass"/> </aspects> </aspectj>
然后同样在切面项目的pom.xml里配置AspectJ编译插件(和方案一的第一步一样),执行mvn clean install安装到本地仓库。
第二步:引入项目的配置
在新的项目里只需要添加依赖:
<dependencies> <dependency> <groupId>你的项目groupId</groupId> <artifactId>你的切面项目artifactId</artifactId> <version>你的版本号</version> </dependency> <!-- 引入AspectJ织入代理依赖 --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.9.1</version> </dependency> </dependencies>
然后运行项目时,给JVM加启动参数:
-javaagent:/你的本地仓库路径/org/aspectj/aspectjweaver/1.9.9.1/aspectjweaver-1.9.9.1.jar
如果是用Maven运行项目,也可以在pom.xml里配置exec插件自动加参数:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <configuration> <mainClass>你的主类全限定名</mainClass> <arguments> <argument>-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/1.9.9.1/aspectjweaver-1.9.9.1.jar</argument> </arguments> </configuration> </plugin> </plugins> </build>
这样JVM启动时,AspectJ的织入代理会读取aop.xml配置,动态把切面织入到目标类中,切面就生效了。
几个关键注意点
- 你的自定义注解一定要加
@Retention(RetentionPolicy.RUNTIME),不然AspectJ运行时识别不到; - 切面类必须标注
@Aspect注解,切点表达式要正确匹配你的注解,比如@Pointcut("@annotation(com.your.annotation.YourCustomAnnotation)"); - AspectJ的几个依赖(aspectjrt、aspectjtools、aspectjweaver)版本要统一,避免版本冲突。
内容的提问来源于stack exchange,提问作者FiguringThisOut

