javamavenaopaspectjaspectj-maven-plugin

AspectJ: How to weave an aspect library into a Java project


I build small library (Java and Maven) - using AspectJ. Library must be independent. Library deliver Aspects and Annotations. Function of library is - "call advice when executed a method with specific annotation". All is ok when I use everything in one module, but problem appers when i separate library and project with classes which advice must be applied. I create simple schema. Schema Library B - my library (aspects and annotations) Project A - project with buisness methods which adivce must be applied Is any posibility to do this?


Solution

  • According to the AspectJ Maven documentation, chapter "using aspect libraries", you need to

    Here is a concrete example:

    Aspect library POM, marker annotation and sample aspect:

    <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>aspectj-lib</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    
        <name>AspectJ Library</name>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.source-target.version>1.8</java.source-target.version>
            <aspectj.version>1.8.7</aspectj.version>
        </properties>
    
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.3</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.7</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>
                        </dependencies>
                    </plugin>
                </plugins>
            </pluginManagement>
            <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>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjrt</artifactId>
                    <version>${aspectj.version}</version>
                    <scope>runtime</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
            </dependency>
        </dependencies>
    
        <organization>
            <name>Scrum-Master.de - Agile Project Management</name>
            <url>http://scrum-master.de</url>
        </organization>
    
    </project>
    
    package de.scrum_master.aspect;
    
    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 Marker {}
    
    package de.scrum_master.aspect;
    
    public aspect MyAspect {
        before() : execution(* *(..)) && @annotation(Marker) {
            System.out.println(thisJoinPoint);
        }
    }
    

    Now run mvn clean install on the aspect library project so as to install the dependency into your local Maven repo.

    Java application POM and sample application:

    By the way, in the POM I have also added two optional plugins:

    These two are only for convenience, you do not need them if you dislike them.

    <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>java-app</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    
        <name>Java Application</name>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <java.source-target.version>1.8</java.source-target.version>
            <aspectj.version>1.8.7</aspectj.version>
            <main-class>de.scrum_master.app.Application</main-class>
        </properties>
    
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.3</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.7</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> -->
                            <aspectLibraries>
                                <aspectLibrary>
                                    <groupId>de.scrum-master.stackoverflow</groupId>
                                    <artifactId>aspectj-lib</artifactId>
                                </aspectLibrary>
                            </aspectLibraries>
                        </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>
                        </dependencies>
                    </plugin>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                        <version>1.4.0</version>
                        <configuration>
                            <mainClass>${main-class}</mainClass>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.dstovall</groupId>
                        <artifactId>onejar-maven-plugin</artifactId>
                        <version>1.4.4</version>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>one-jar</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <onejarVersion>0.96</onejarVersion>
                            <mainClass>${main-class}</mainClass>
                            <attachToBuild>true</attachToBuild>
                        </configuration>
                    </plugin>
                </plugins>
            </pluginManagement>
            <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>
                -->
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <configuration>
                        <mainClass>${main-class}</mainClass>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.dstovall</groupId>
                    <artifactId>onejar-maven-plugin</artifactId>
                    <configuration>
                        <mainClass>${main-class}</mainClass>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <pluginRepositories>
            <pluginRepository>
                <id>OneJAR googlecode.com</id>
                <url>http://onejar-maven-plugin.googlecode.com/svn/mavenrepo</url>
            </pluginRepository>
        </pluginRepositories>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjrt</artifactId>
                    <version>${aspectj.version}</version>
                    <scope>runtime</scope>
                </dependency>
                <dependency>
                    <groupId>de.scrum-master.stackoverflow</groupId>
                    <artifactId>aspectj-lib</artifactId>
                    <version>0.0.1-SNAPSHOT</version>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
            </dependency>
                <dependency>
                    <groupId>de.scrum-master.stackoverflow</groupId>
                    <artifactId>aspectj-lib</artifactId>
                </dependency>
        </dependencies>
    
        <organization>
            <name>Scrum-Master.de - Agile Project Management</name>
            <url>http://scrum-master.de</url>
        </organization>
    
    </project>
    

    This little driver application demonstrates that you can now annotate methods with @Marker, in this case only foo and zot, but not bar:

    package de.scrum_master.app;
    
    import de.scrum_master.aspect.Marker;
    
    public class Application {
        @Marker
        public static void foo() {}
    
        public static void bar() {}
    
        @Marker
        public static void zot() {}
    
        public static void main(String[] args) {
            foo();
            bar();
            zot();
        }
    }
    

    Console log:

    java -jar target/java-app-0.0.1-SNAPSHOT.one-jar.jar
    
    execution(void de.scrum_master.app.Application.foo())
    execution(void de.scrum_master.app.Application.zot())