はじめに
あるOSSの解析のためにAspectJを利用した。 その際にMavenでアスペクトのビルドとテストを行ったので、その記録を残しておく。 ここでは、テストメソッドにログ出力を織り込むことにする。
ディレクトリ構成
$ tree . |-- pom.xml `-- src |-- main | |-- java | | `-- redj | | `-- aspectj | | `-- LoggingAspect.java | `-- resources `-- test `-- java `-- redj `-- aspectj `-- LoggingAspectTest.java
LoggingAspect.java
アスペクトを準備。 パッケージredj.aspectjの任意のクラスにおいて、testをプレフィックスに持つメソッドの実行前にログを出力する。
package redj.aspectj; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class LoggingAspect { @Pointcut("execution(* redj.aspectj.*.test*(..))") public void atTestMethod() { } @Before("atTestMethod()") public void logBeforeTest() { System.out.println("***** begin test"); } }
LoggingAspectTest.java
テストクラスを準備。 アスペクトが織り込まれるように、testをプレフィックスに持つメソッドを定義しておく。
package redj.aspectj; import org.junit.Test; public class LoggingAspectTest { @Test public void testFoo() { System.out.println("test foo"); } @Test public void testBar() { System.out.println("test bar"); } }
pom.xml
testフェーズでLoad-Time Weavingを利用するようにpom.xmlを構成。 かなり面倒。
maven-dependency-plugin:build-classpathを利用してaspectjweaverのJarファイルのパスを組み立てて、maven-surefire-plugin:testに引き渡しているところがポイント。 maven-surefire-plugin:testでは、プロパテイを遅延評価する必要があるので@{ }を利用している。
aspectj-maven-plugin:compileを利用してaop-ajc.xmlを生成する。 aop-ajc.xmlには、aspectjweaverに認識させるアスペクトの定義情報が書かれている。 ただし、aspectj-maven-pluginのcomplianceLevelのデフォルトは1.4なので、明示的に1.5以上に設定しないと、アノテーションを利用したアスペクトのコンパイルでエラーを起こす。 さらに、AspectJのバージョンがずれていると警告が出るので、aspectj-maven-pluginにaspectjtoolsへの依存を明示的に書いて、バージョンを合わせる。
<?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>redj</groupId> <artifactId>aspectj</artifactId> <version>0.0.1</version> <packaging>jar</packaging> <properties> <!-- maven-compiler-plugin --> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <!-- versions of plugins --> <maven-dependency-plugin.version>3.0.0</maven-dependency-plugin.version> <aspectj-maven-plugin.version>1.10</aspectj-maven-plugin.version> <maven-surefire-plugin.version>2.20</maven-surefire-plugin.version> <!-- versions of dependencies --> <aspectj.version>1.8.10</aspectj.version> <junit.version>4.12</junit.version> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>${maven-dependency-plugin.version}</version> <executions> <execution> <goals> <goal>build-classpath</goal> <!-- binds by default to generate-sources --> </goals> <configuration> <outputProperty>aspectj-weaver-path</outputProperty> <includeGroupIds>org.aspectj</includeGroupIds> <includeArtifactIds>aspectjweaver</includeArtifactIds> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>${aspectj-maven-plugin.version}</version> <dependencies> <dependency> <!-- upgrade AspectJ --> <groupId>org.aspectj</groupId> <artifactId>aspectjtools</artifactId> <version>${aspectj.version}</version> </dependency> </dependencies> <executions> <execution> <goals> <goal>compile</goal> <!-- binds by default to compile --> </goals> <configuration> <complianceLevel>1.8</complianceLevel> <outxml>true</outxml> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>${maven-surefire-plugin.version}</version> <executions> <execution> <id>default-test</id> <goals> <goal>test</goal> <!-- binds by default to test --> </goals> <configuration> <argLine>-javaagent:@{aspectj-weaver-path}</argLine> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> </project>
ビルド
テストメソッドの実行前にログが出力されていることが確認できる。
$ mvn clean install (略) [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running redj.aspectj.LoggingAspectTest ***** begin test test bar ***** begin test test foo [INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.153 s - in redj.aspectj.LoggingAspectTest (略)