问题
I'm trying to do AOP with Aspectj, but I don't know why is not executing my aspect, it just runs the main class. Is the first time I do this, so I might be doing something wrong.
This is my code:
The Aspect:
@Aspect
public class YourAspect {
@Pointcut("@annotation(yourAnnotationVariableName)")
public void annotationPointCutDefinition(YourAnnotation yourAnnotationVariableName){
}
@Pointcut("execution(* *(..))")
public void atExecution(){}
@Around("annotationPointCutDefinition(yourAnnotationVariableName) && atExecution()")
public Object aroundAdvice(ProceedingJoinPoint joinPoint, YourAnnotation yourAnnotationVariableName) throws Throwable {
if(yourAnnotationVariableName.isRun()) {
Object returnObject = null;
try {
System.out.println("aspects.YourAspect's aroundAdvice's body is now executed Before yourMethodAround is called.");
returnObject = joinPoint.proceed();
} catch (Throwable throwable) {
throw throwable;
} finally {
System.out.println("aspects.YourAspect's aroundAdvice's body is now executed After yourMethodAround is called.");
}
return returnObject;
}
return joinPoint.proceed();
}
@After("annotationPointCutDefinition(yourAnnotationVariableName) && atExecution()")
public void printNewLine(JoinPoint pointcut, YourAnnotation yourAnnotationVariableName){
System.out.print("End\n\r");
}
}
The annotation:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface YourAnnotation {
public boolean isRun() default true;
}
The Main class:
public class MainClass{
public static void main(String[] args) {
MainClass yourClass = new MainClass ();
yourClass.yourMethodAround();
}
@YourAnnotation
public void yourMethodAround(){
System.out.println("Executing TestTarget.yourMethodAround()");
}
}
I'm working with two modules, and the POMs looks like this:
Aspect's 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>Group</groupId>
<artifactId>Aspects</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</version>
</dependency>
</dependencies>
</project>
Main 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>Group</groupId>
<artifactId>Main</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<pluginManagement>
<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>
<aspectLibraries>
<aspectLibrary>
<groupId>Group</groupId>
<artifactId>Aspects</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>aspects.MainClass</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>a-make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>aspects.MainClass</mainClass>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>Group</groupId>
<artifactId>Aspects</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
I did mvn clean install in both projects and then mvn exec:java in the Main project, and it just runs the method, not the aspects. Can anyone help me?
Thank you!
回答1:
Here is a multi-module solution.
Main POM (parent for all others):
Here we define all plugins with basic configuration (more specific configuration can be found in "application" module) and manage all dependency versions.
<?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>de.scrum-master.stackoverflow</groupId>
<artifactId>main</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.source-target.version>1.8</java.source-target.version>
<aspectj.version>1.8.10</aspectj.version>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<!-- IMPORTANT -->
<useIncrementalCompilation>false</useIncrementalCompilation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.10</version>
<configuration>
<!--<showWeaveInfo>true</showWeaveInfo> -->
<source>${java.source-target.version}</source>
<target>${java.source-target.version}</target>
<Xlint>ignore</Xlint>
<complianceLevel>${java.source-target.version}</complianceLevel>
<encoding>${project.build.sourceEncoding}</encoding>
<!--<verbose>true</verbose> -->
<!--<warn>constructorName,packageDefaultMethod,deprecation,maskedCatchBlocks,unusedLocals,unusedArguments,unusedImport</warn> -->
</configuration>
<executions>
<execution>
<!-- IMPORTANT -->
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.5.5</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>a-make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>aspect</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>common</module>
<module>application</module>
<module>aspect</module>
</modules>
</project>
Module "common":
This module contains code used by both "application" and "aspect", more specifically in this case the annotation class.
<?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>
<parent>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>main</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>common</artifactId>
</project>
package de.scrum_master.common;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface YourAnnotation {
boolean isRun() default true;
}
Module "aspect":
Here we just have the aspect code.
<?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>
<parent>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>main</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>aspect</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>common</artifactId>
</dependency>
</dependencies>
</project>
package de.scrum_master.aspect;
import de.scrum_master.common.YourAnnotation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class YourAspect {
@Pointcut("@annotation(yourAnnotationVariableName)")
public void annotationPointCutDefinition(YourAnnotation yourAnnotationVariableName) {
}
@Pointcut("execution(* *(..))")
public void atExecution() {
}
@Around("annotationPointCutDefinition(yourAnnotationVariableName) && atExecution()")
public Object aroundAdvice(ProceedingJoinPoint thisJoinPoint, YourAnnotation yourAnnotationVariableName) throws Throwable {
if (yourAnnotationVariableName.isRun()) {
Object result;
try {
System.out.println("Before " + thisJoinPoint);
result = thisJoinPoint.proceed();
} catch (Throwable t) {
throw t;
} finally {
System.out.println("After " + thisJoinPoint);
}
return result;
}
return thisJoinPoint.proceed();
}
}
Module "application":
This module contains the application code. It configures both the Exec Maven and Maven Assembly plugins. Furthermore is defines the "aspect" module as an aspect library for AspectJ Maven.
<?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>
<parent>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>main</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>application</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>de.scrum_master.app.MainClass</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<mainClass>de.scrum_master.app.MainClass</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<aspectLibraries>
<aspectLibrary>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>aspect</artifactId>
</aspectLibrary>
</aspectLibraries>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>common</artifactId>
</dependency>
<dependency>
<groupId>de.scrum-master.stackoverflow</groupId>
<artifactId>aspect</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
</dependencies>
</project>
package de.scrum_master.app;
import de.scrum_master.common.YourAnnotation;
public class MainClass {
public static void main(String[] args) {
MainClass yourClass = new MainClass();
yourClass.yourMethodAround();
}
@YourAnnotation
public void yourMethodAround() {
System.out.println("Executing TestTarget.yourMethodAround()");
}
}
Build log:
Alexander@Xander-PC MINGW64 ~/Documents/java-src/SO_AJ_MavenMultiModuleProblem
$ mvn clean install
(...)
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] main ............................................... SUCCESS [ 0.241 s]
[INFO] common ............................................. SUCCESS [ 0.970 s]
[INFO] aspect ............................................. SUCCESS [ 1.058 s]
[INFO] application ........................................ SUCCESS [ 0.607 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.111 s
[INFO] Finished at: 2017-04-07T17:15:39+02:00
[INFO] Final Memory: 23M/378M
[INFO] ------------------------------------------------------------------------
Run log:
Alexander@Xander-PC MINGW64 ~/Documents/java-src/SO_AJ_MavenMultiModuleProblem
$ cd application/
Alexander@Xander-PC MINGW64 ~/Documents/java-src/SO_AJ_MavenMultiModuleProblem/application
$ mvn exec:java
(...)
[INFO] ------------------------------------------------------------------------
[INFO] Building application 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- exec-maven-plugin:1.5.0:java (default-cli) @ application ---
Before execution(void de.scrum_master.app.MainClass.yourMethodAround())
Executing TestTarget.yourMethodAround()
After execution(void de.scrum_master.app.MainClass.yourMethodAround())
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
(...)
Alexander@Xander-PC MINGW64 ~/Documents/java-src/SO_AJ_MavenMultiModuleProblem/application
$ java -jar target/application-1.0-SNAPSHOT.jar
Before execution(void de.scrum_master.app.MainClass.yourMethodAround())
Executing TestTarget.yourMethodAround()
After execution(void de.scrum_master.app.MainClass.yourMethodAround())
Update: I pushed the whole sample project to a GitHub repository.
回答2:
OK here you go. I didn't split up things in different projects/packages to keep it as simple as possible.
Project pom.xml:
<?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>Group</groupId>
<artifactId>Main</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.10</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>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>yourpackage.AspectJRawTest</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Annotation (you wrote this one correctly):
package yourpackage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyCustomAnnotation {
public boolean isRun() default true;
}
Custom advice which will be run before annotated methods. I am not sure about this one, terminology is not absolutely clear to me... but it seems to work :)
package yourpackage;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class MyCustomAspect {
@Before("execution(* *.*(..)) && @annotation(MyCustomAnnotation)")
public void advice(JoinPoint joinPoint) {
System.out.printf("BINGO! advice() called before '%s'%n", joinPoint);
}
}
Lastly, the main class:
package yourpackage;
public class AspectJRawTest {
public static void main(String[] args) {
System.out.println("custom annotation playground");
ISomething something = new SomethingImpl();
something.annotatedMethod();
something.notAnnotatedMethod();
}
}
interface ISomething {
void annotatedMethod();
void notAnnotatedMethod();
}
class SomethingImpl implements ISomething {
@MyCustomAnnotation
public void annotatedMethod() {
System.out.println("I am annotated and something must be printed by an advice above.");
}
public void notAnnotatedMethod() {
System.out.println("I am not annotated and I will not get any special treatment.");
}
}
I build it with maven like this: mvn clean compile assembly:single
to create an executable jar with dependencies included. Then, execute:
java -jar target/Main-1.0-SNAPSHOT-jar-with-dependencies.jar
custom annotation playground
BINGO! advice() called before 'execution(void yourpackage.SomethingImpl.annotatedMethod())'
I am annotated and something must be printed by an advice above.
I am not annotated and I will not get any special treatment.
I will upload a full project somewhere later and provide a link for you, but what I've posted should be sufficient.
I've tested this in IDEA and I couldn't configure it to do proper weaving for me (name any other IDE, you'll get the same problem). But I have no time for this right now, you will have to deal with that task by yourself. Good news, it must be possible since everything works with bare-bone maven.
来源:https://stackoverflow.com/questions/43260618/aspectj-advice-does-not-fire-in-maven-multi-module-setup