Java, custom annotation, AspectJ, Maven: minimalist example
08 Apr 2017
Goal: some code must be executed before/after a method annotated with custom annotation.
We need a custom annotation first:
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 ;
}
An aspect:
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 );
}
}
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>
Main class:
package yourpackage ;
import java.lang.annotation.Annotation ;
import java.lang.reflect.Method ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;
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." );
CalledFromAnnotatedMethod ca = new CalledFromAnnotatedMethod ();
}
public void notAnnotatedMethod () {
System . out . println ( "I am not annotated and I will not get any special treatment." );
CalledFromAnnotatedMethod ca = new CalledFromAnnotatedMethod ();
}
}
/**
* Imagine this is your bean which needs to know if any annotations affected its construction
*/
class CalledFromAnnotatedMethod {
CalledFromAnnotatedMethod () {
List < Annotation > ants = new ArrayList < Annotation >();
for ( StackTraceElement elt : Thread . currentThread (). getStackTrace ()) {
try {
Method m = Class . forName ( elt . getClassName ()). getMethod ( elt . getMethodName ());
ants . addAll ( Arrays . asList ( m . getAnnotations ()));
} catch ( ClassNotFoundException ignored ) {
} catch ( NoSuchMethodException ignored ) {
}
}
System . out . println ( ants );
}
}
Assemble using maven:
mvn clean compile assembly:single
An executable jar with dependencies included will be created.
Output:
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.