4

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!

kriegaex
  • 63,017
  • 15
  • 111
  • 202
Motomine
  • 4,205
  • 5
  • 20
  • 23
  • Are you literally using `yourAnnotationVariableName` in your pointcut? It should have the annotation type as its parameter https://blog.jayway.com/2015/09/08/defining-pointcuts-by-annotations/ – Leonard Brünings Apr 06 '17 at 16:52
  • I followed that web page. What do you mean to using yourAnnotationVariableName in my pointcut? Could you explain a bit more? – Motomine Apr 06 '17 at 16:55
  • There are several problems and false assumptions with regard to Maven multi-module projects in general and how to use AspectJ Maven plugin in particular. For instance, the aspect module does not configure any plugin versions, but also does not use the main module as a parent. And even if it did, it would mean a circular reference because if the aspect module dependes on main and main has aspects as a dependency, this cannot compile. I suggest you create a common parent and then an application and an aspect module with the correct configuration (I can help you with that). – kriegaex Apr 07 '17 at 10:36
  • Furthermore, you might want to consider to add another module for common classes used by both aspect and application module, in which you put the annotation class used by both. Otherwise you need to put the annotation class into the aspect module. Putting everything into s single-module project as shown by @Mikhail Antonov is a simplifying workaround, but if you have reasons to create a re-useable aspect module, that would not work. – kriegaex Apr 07 '17 at 10:37
  • Thank you for the help! I've managed to make it work in differents projects, but I think that I have a lot of things in my project pom, is there any way to minify that? The code is below! – Motomine Apr 07 '17 at 13:30

2 Answers2

5

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.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • That's a good solution! I'll try it in a while. What I like about doing this is that I run mvn clean isntall over the parent pom and all of them are compiled. But with happen if one of my modules has different profiles? How can I specify it in that case? Now I do mvn clean install -Pprofile, but in this case I will run it on the parent, not in the child. Thank you! – Motomine Apr 07 '17 at 15:27
  • I do not understand the question. If you run the main build with `-Pprofile`, the profile will apply to all modules where that profile exists. – kriegaex Apr 07 '17 at 15:37
  • I didn't know that. Because the profile only exists in one module and not in the other. I thought that I had a trick behind this. I'll try it ! thank you! – Motomine Apr 07 '17 at 15:49
  • I don't understand at all when do you have to write the plugin or dependency that is written on the parent pom, because sometimes you do it and sometimes not. What's the difference? – Motomine Apr 07 '17 at 18:04
  • You have to use all my code and all my POMs, not just parts. You have not done so, I can easily spot that because I use version 1.10 of AspectJ Maven, you still use 1.7. Thus, you must have mixed and somehow messed up the setup. – kriegaex Apr 07 '17 at 19:02
  • As for why I declare some plugins and dependencies in the main POM, please note that it is not in the `plugins` section but in the `pluginManagement` section and not in `dependencies` but in `dependencyManagement`. I.e. I only preconfigure the versions and some settings. The child POMs then declare what they really need, but inheriting versions and basic configuration from the parent, only referring to the preconfigured stuff and for plugins overriding module-specific config settings. Please read a Maven tutorial in order to understand the difference. – kriegaex Apr 07 '17 at 19:03
  • **Update:** I pushed the whole sample project to a [GitHub repository](https://github.com/kriegaex/SO_AJ_MavenMultiModuleProblem) for your convenience. Just clone the repo and be happy. – kriegaex Apr 07 '17 at 19:10
  • I've been using maven for a long time, but I've never used a parent pom even when I know that exists, because I've never had to use it. Thank you for the explanation! – Motomine Apr 07 '17 at 20:01
1

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.

Mikhail Antonov
  • 1,297
  • 3
  • 21
  • 29