简体   繁体   中英

AspectJ Aspects not getting triggered in Maven Project

I am trying to build a POC project using AspectJ without using Spring AOP . I am using an annotation based approach where I want to run the aspect @Around the method which has been annotated with an annotation. For some reason my aspects don't get triggered. Below is my code:

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>

My Aspect:

@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;
    }
}

The annotated method

@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;
}

I can't seem to figure it out as to what am I missing. I have uploaded the sample code on GitHub here .

You are using AspectJ Maven Plugin, ie you are going to use compile-time weaving. Therefore, you do not need aop.xml because that one is used for load-time weaving. So you can delete it.

During compilation you should get a compile error:

Unbound pointcut parameter 'dataTrackEnabled'

That tells you that your advice method has a parameter dataTrackEnabled which does not occur anywhere in the pointcut as it should. So just change the pointcut from

@Around("@annotation(com.carrot.personal.aspects.DataTrackEnabled)")

to

@Around("@annotation(dataTrackEnabled)")

As you see, I am referring to the method parameter name from the pointcut. If you would not bind the annotation to a parameter, then you would need the fully qualified class name as you used it before.

Also, your Maven POM should cause this error:

diamond operator is not supported in -source 1.5

This is because using AspectJ Maven does not automatically deactivate or replace Maven Compiler Plugin and the latter complains that you did not set source and target versions for it. So you have two options:

  1. Deactivate Maven Compiler, let AspectJ Maven compile your Java and aspect classes.
  2. Set the compiler level to 1.8 (or simply 8) for Maven Compiler and use the same settings for AspectJ Maven.

I will choose option no. 2 in this case. Maven knows properties named maven.compiler.source and maven.compiler.target . Let us define and use them:

  <!-- (...) -->

  <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>

  <!-- (...) -->

Now there are a few more warnings:

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\1.8.9\aspectjrt-1.8.9.jar expected 1.8.2 found 1.8.9

The first two are just because you forgot to set <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> . While you are at it, you can set the encoding for generated reports, too: <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> .

The last one is aspect-related and due to the fact that AspectJ Maven 1.7 depends on AspectJ 1.8.2 , not 1.8.9. But be careful! It depends on aspectjtools (for using the compiler), not on aspectjweaver (for load-time weaving). You can either upgrade the version or override the dependency inside the plugin. I am going to show you both at the same time, just in case.

Last but not least, the latest version of AspectJ 1.8 is 1.8.13. But you can just use the very latest version 1.9.6, it supports up to Java 14 (the next version for Java 15+16 is almost ready) and can still produce byte code for Java 8.

How about this 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>

Now when you run the program, you should see something like:

Recording: dataClass = Hey, dataName = There, instance = How are you?
Recording: dataClass = Hey, dataName = There, instance = How are you?

You may ask why the advice is triggered twice. Well, just because @annotation(dataTrackEnabled) captures both the method call() and the method execution() pointcut. So let us limit the match to just executions.

The full solution looks like this (do not forget RUNTIME retention for your annotation):

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;
  }
}

I added some more log output, so let us run the application again:

execution(Map com.carrot.personal.app.Application.fetchUser())
Recording: dataClass = Hey, dataName = There, instance = How are you?
{firstName=carrot, lastName=radish}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM