Maven 项目中未触发 AspectJ 方面
AspectJ Aspects not getting triggered in Maven Project
我正在尝试使用 AspectJ
而不使用 Spring AOP
构建 POC 项目。我正在使用基于注释的方法,我想 运行 方面 @Around
已经用注释注释的方法。出于某种原因,我的方面没有被触发。下面是我的代码:
pom.xml
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
resources/META-INF/aop.xml
<aspectj>
<aspects>
<aspect name="com.aditya.personal.aspects.MetricsAspect"/>
<weaver options="-verbose -showWeaveInfo">
<include within="com.carrot.personal.aspects.*"/>
</weaver>
</aspects>
</aspectj>
我的看点:
@Aspect
public class DataTrackAspect {
@Around("@annotation(com.carrot.personal.aspects.DataTrackEnabled)")
public Object performAspect(ProceedingJoinPoint joinPoint, DataTrackEnabled dataTrackEnabled) throws Throwable {
Object result = joinPoint.proceed();
DataTrackHelper dataTrackHelper = new DataTrackHelper();
dataTrackHelper.recordInstanceCount(dataTrackEnabled.dataClass(), dataTrackEnabled.dataName(), dataTrackEnabled.instance());
return result;
}
}
注释方法
@DataTrackEnabled(dataClass = "Hey", dataName = "There", instance = "How are you?")
public Map<String, String> fetchUser() {
Map<String, String> returnable = new HashMap<>();
returnable.put("firstName", "carrot");
returnable.put("lastName", "radish");
return returnable;
}
我似乎无法弄清楚我错过了什么。我已经上传了示例代码 on GitHub here.
您正在使用 AspectJ Maven 插件,即您将使用编译时织入。因此,您不需要 aop.xml,因为它用于加载时织入。所以你可以删除它。
在编译过程中你应该得到一个编译错误:
Unbound pointcut parameter 'dataTrackEnabled'
这告诉你你的建议方法有一个参数 dataTrackEnabled
它没有出现在切入点的任何地方。所以只需将切入点从
@Around("@annotation(com.carrot.personal.aspects.DataTrackEnabled)")
至
@Around("@annotation(dataTrackEnabled)")
如您所见,我指的是切入点中的方法参数名称。如果您不将注释绑定到参数,那么您将需要您之前使用的完全限定的 class 名称。
此外,您的 Maven POM 应该会导致此错误:
diamond operator is not supported in -source 1.5
这是因为使用 AspectJ Maven 不会自动停用或替换 Maven Compiler Plugin,而后者会抱怨您没有为其设置源版本和目标版本。所以你有两个选择:
- 停用 Maven 编译器,让 AspectJ Maven 编译您的 Java 和方面 classes。
- 将 Maven 编译器的编译器级别设置为 1.8(或简称为 8),并对 AspectJ Maven 使用相同的设置。
我会选择第一个选项。 2 在这种情况下。 Maven 知道名为 maven.compiler.source
and maven.compiler.target
的属性。让我们定义并使用它们:
<!-- (...) -->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!-- (...) -->
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>${maven.compiler.target}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<!-- (...) -->
现在多了几个警告:
Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
bad version number found in C:\Users\alexa\.m2\repository\org\aspectj\aspectjrt.8.9\aspectjrt-1.8.9.jar expected 1.8.2 found 1.8.9
前两个只是因为你忘了设置<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
。同时,您还可以为生成的报告设置编码:<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
.
最后一个是方面相关的,因为 AspectJ Maven 1.7 depends on AspectJ 1.8.2,不是 1.8.9。不过要小心!它取决于 aspectjtools
(用于使用编译器),而不取决于 aspectjweaver
(用于加载时织入)。您可以升级版本或覆盖插件内的依赖项。为了以防万一,我打算同时给你们看。
最后但同样重要的是,AspectJ 1.8 的最新版本是 1.8.13。但是你可以使用最新的1.9.6版本,它最多支持Java 14(Java 15+16的下一个版本已经准备好了)并且仍然可以生成[=77的字节码=] 8.
这个 POM 怎么样?
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.carrot</groupId>
<artifactId>SO_AJ_MavenProjectNotWorking_66734262</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<aspectj.version>1.9.6</aspectj.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>${maven.compiler.target}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</project>
现在,当您 运行 程序时,您应该会看到如下内容:
Recording: dataClass = Hey, dataName = There, instance = How are you?
Recording: dataClass = Hey, dataName = There, instance = How are you?
你可能会问为什么建议被触发了两次。好吧,只是因为 @annotation(dataTrackEnabled)
捕获了方法 call()
和方法 execution()
切入点。因此,让我们将匹配限制为执行。
完整的解决方案如下所示(不要忘记 RUNTIME
保留注释):
package com.carrot.personal.aspects;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface DataTrackEnabled {
String dataClass();
String dataName();
String instance();
}
package com.carrot.personal.app;
public class DataTrackHelper {
public void recordInstanceCount(String dataClass, String dataName, String instance) {
System.out.println("Recording: dataClass = " + dataClass + ", dataName = " + dataName + ", instance = " + instance);
}
}
package com.carrot.personal.app;
import com.carrot.personal.aspects.DataTrackEnabled;
import java.util.HashMap;
import java.util.Map;
public class Application {
public static void main(String[] args) {
System.out.println(new Application().fetchUser());
}
@DataTrackEnabled(dataClass = "Hey", dataName = "There", instance = "How are you?")
public Map<String, String> fetchUser() {
Map<String, String> returnable = new HashMap<>();
returnable.put("firstName", "carrot");
returnable.put("lastName", "radish");
return returnable;
}
}
package com.carrot.personal.aspects;
import com.carrot.personal.app.DataTrackHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class DataTrackAspect {
@Around("@annotation(dataTrackEnabled) && execution(* *(..))")
public Object performAspect(ProceedingJoinPoint joinPoint, DataTrackEnabled dataTrackEnabled) throws Throwable {
System.out.println(joinPoint);
Object result = joinPoint.proceed();
DataTrackHelper dataTrackHelper = new DataTrackHelper();
dataTrackHelper.recordInstanceCount(dataTrackEnabled.dataClass(), dataTrackEnabled.dataName(), dataTrackEnabled.instance());
return result;
}
}
我添加了更多日志输出,所以让我们再次 运行 应用程序:
execution(Map com.carrot.personal.app.Application.fetchUser())
Recording: dataClass = Hey, dataName = There, instance = How are you?
{firstName=carrot, lastName=radish}
我正在尝试使用 AspectJ
而不使用 Spring AOP
构建 POC 项目。我正在使用基于注释的方法,我想 运行 方面 @Around
已经用注释注释的方法。出于某种原因,我的方面没有被触发。下面是我的代码:
pom.xml
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>1.8</complianceLevel>
<source>1.8</source>
<target>1.8</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
resources/META-INF/aop.xml
<aspectj>
<aspects>
<aspect name="com.aditya.personal.aspects.MetricsAspect"/>
<weaver options="-verbose -showWeaveInfo">
<include within="com.carrot.personal.aspects.*"/>
</weaver>
</aspects>
</aspectj>
我的看点:
@Aspect
public class DataTrackAspect {
@Around("@annotation(com.carrot.personal.aspects.DataTrackEnabled)")
public Object performAspect(ProceedingJoinPoint joinPoint, DataTrackEnabled dataTrackEnabled) throws Throwable {
Object result = joinPoint.proceed();
DataTrackHelper dataTrackHelper = new DataTrackHelper();
dataTrackHelper.recordInstanceCount(dataTrackEnabled.dataClass(), dataTrackEnabled.dataName(), dataTrackEnabled.instance());
return result;
}
}
注释方法
@DataTrackEnabled(dataClass = "Hey", dataName = "There", instance = "How are you?")
public Map<String, String> fetchUser() {
Map<String, String> returnable = new HashMap<>();
returnable.put("firstName", "carrot");
returnable.put("lastName", "radish");
return returnable;
}
我似乎无法弄清楚我错过了什么。我已经上传了示例代码 on GitHub here.
您正在使用 AspectJ Maven 插件,即您将使用编译时织入。因此,您不需要 aop.xml,因为它用于加载时织入。所以你可以删除它。
在编译过程中你应该得到一个编译错误:
Unbound pointcut parameter 'dataTrackEnabled'
这告诉你你的建议方法有一个参数 dataTrackEnabled
它没有出现在切入点的任何地方。所以只需将切入点从
@Around("@annotation(com.carrot.personal.aspects.DataTrackEnabled)")
至
@Around("@annotation(dataTrackEnabled)")
如您所见,我指的是切入点中的方法参数名称。如果您不将注释绑定到参数,那么您将需要您之前使用的完全限定的 class 名称。
此外,您的 Maven POM 应该会导致此错误:
diamond operator is not supported in -source 1.5
这是因为使用 AspectJ Maven 不会自动停用或替换 Maven Compiler Plugin,而后者会抱怨您没有为其设置源版本和目标版本。所以你有两个选择:
- 停用 Maven 编译器,让 AspectJ Maven 编译您的 Java 和方面 classes。
- 将 Maven 编译器的编译器级别设置为 1.8(或简称为 8),并对 AspectJ Maven 使用相同的设置。
我会选择第一个选项。 2 在这种情况下。 Maven 知道名为 maven.compiler.source
and maven.compiler.target
的属性。让我们定义并使用它们:
<!-- (...) -->
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<!-- (...) -->
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>${maven.compiler.target}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<!-- (...) -->
现在多了几个警告:
Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
bad version number found in C:\Users\alexa\.m2\repository\org\aspectj\aspectjrt.8.9\aspectjrt-1.8.9.jar expected 1.8.2 found 1.8.9
前两个只是因为你忘了设置<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
。同时,您还可以为生成的报告设置编码:<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
.
最后一个是方面相关的,因为 AspectJ Maven 1.7 depends on AspectJ 1.8.2,不是 1.8.9。不过要小心!它取决于 aspectjtools
(用于使用编译器),而不取决于 aspectjweaver
(用于加载时织入)。您可以升级版本或覆盖插件内的依赖项。为了以防万一,我打算同时给你们看。
最后但同样重要的是,AspectJ 1.8 的最新版本是 1.8.13。但是你可以使用最新的1.9.6版本,它最多支持Java 14(Java 15+16的下一个版本已经准备好了)并且仍然可以生成[=77的字节码=] 8.
这个 POM 怎么样?
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.carrot</groupId>
<artifactId>SO_AJ_MavenProjectNotWorking_66734262</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<aspectj.version>1.9.6</aspectj.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<complianceLevel>${maven.compiler.target}</complianceLevel>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<showWeaveInfo>true</showWeaveInfo>
<verbose>true</verbose>
<Xlint>ignore</Xlint>
<encoding>UTF-8</encoding>
</configuration>
<executions>
<execution>
<goals>
<!-- use this goal to weave all your main classes -->
<goal>compile</goal>
<!-- use this goal to weave all your test classes -->
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</project>
现在,当您 运行 程序时,您应该会看到如下内容:
Recording: dataClass = Hey, dataName = There, instance = How are you?
Recording: dataClass = Hey, dataName = There, instance = How are you?
你可能会问为什么建议被触发了两次。好吧,只是因为 @annotation(dataTrackEnabled)
捕获了方法 call()
和方法 execution()
切入点。因此,让我们将匹配限制为执行。
完整的解决方案如下所示(不要忘记 RUNTIME
保留注释):
package com.carrot.personal.aspects;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface DataTrackEnabled {
String dataClass();
String dataName();
String instance();
}
package com.carrot.personal.app;
public class DataTrackHelper {
public void recordInstanceCount(String dataClass, String dataName, String instance) {
System.out.println("Recording: dataClass = " + dataClass + ", dataName = " + dataName + ", instance = " + instance);
}
}
package com.carrot.personal.app;
import com.carrot.personal.aspects.DataTrackEnabled;
import java.util.HashMap;
import java.util.Map;
public class Application {
public static void main(String[] args) {
System.out.println(new Application().fetchUser());
}
@DataTrackEnabled(dataClass = "Hey", dataName = "There", instance = "How are you?")
public Map<String, String> fetchUser() {
Map<String, String> returnable = new HashMap<>();
returnable.put("firstName", "carrot");
returnable.put("lastName", "radish");
return returnable;
}
}
package com.carrot.personal.aspects;
import com.carrot.personal.app.DataTrackHelper;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class DataTrackAspect {
@Around("@annotation(dataTrackEnabled) && execution(* *(..))")
public Object performAspect(ProceedingJoinPoint joinPoint, DataTrackEnabled dataTrackEnabled) throws Throwable {
System.out.println(joinPoint);
Object result = joinPoint.proceed();
DataTrackHelper dataTrackHelper = new DataTrackHelper();
dataTrackHelper.recordInstanceCount(dataTrackEnabled.dataClass(), dataTrackEnabled.dataName(), dataTrackEnabled.instance());
return result;
}
}
我添加了更多日志输出,所以让我们再次 运行 应用程序:
execution(Map com.carrot.personal.app.Application.fetchUser())
Recording: dataClass = Hey, dataName = There, instance = How are you?
{firstName=carrot, lastName=radish}