2014-08-24

[java] Lombok と AspectJ を組み合わせて使う

Lombok はリフレクションなどは使用せず、コンパイル時にゲッターやセッター、ロガー、toString、hashCode, equals など自動生成出来そうなものを生成してくれる大変便利なライブラリです。これと、AspectJ を組み合わせようとすると、厄介な問題が発生したのでメモしておきます。

まず、よく使用されているらしい aspectj-maven-plugin を使おうとすると、ソースコードに対する weaving は Lombok が処理する前のコードをコンパイルして weaving しようとして、コンパイルに失敗しました。そこで処理対象を Java バイトコード (.class) に変更しようとして、この方法 を見つけました。頑張れば出来そうな気はしますが spring-aspects を使うプロジェクトでまだ上手くビルド出来ていません。

次に見つけた、jcabi-maven-plugin の ajc ゴール を使う方法は、特に何も追加の設定をすることなく、Lombok 経由で作られた .class に対して weaving を行ってくれました。この組み合わせが良いと思います。


<!-- project > build > plugins -->
<plugin>
  <groupId>com.jcabi</groupId>
  <artifactId>jcabi-maven-plugin</artifactId>
  <version>0.9.3</version>
  <executions>
    <execution>
      <goals>
        <goal>ajc</goal>
      </goals>
    </execution>
  </executions>
</plugin>

Spring Framework + AspectJ
少し蛇足ですが、@Transactional, @Scheduled, @Async, @Cacheable を使うには、mode = AdviceMode.ASPECTJ に加えて spring-aspects をコンパイル時依存に追加する必要があります。同じく @PreAuthorize, @PostFilter, @Secured など、@EnableGlobalMethodSecurity で有効になる仕組みを使うには spring-security-aspects が必要です。

また実行時依存に aspectjrt も追加しておきましょう。通常時は使われる気配はありませんがこちらの FAQ によると異常時の挙動に関係するようです When I run, I get a NoAspectBoundException or a ClassNotFound message for NoAspectBoundException.

今回はコンパイル時の weaving について記述しましたが実行時の weaving も可能なので、興味のある方は @EnableLoadTimeWeaving のあたりを調べてみてください。