在Java+Lombok阶段后如何使用AspectJ Maven进行二进制编织

我有一个项目,它使用已编译的方面并在编译时编织它们。我想添加龙目岛,但不幸的是龙目岛不支持AJC。因为这个项目本身没有任何方面的源代码,所以我将AspectJ Maven插件配置为在使用Javac+Lombok编译之后进行编译后编织。

以下是AspectJ Maven插件的配置:

<forceAjcCompile>true</forceAjcCompile>
<sources/>
<weaveDirectory>${project.build.outputDirectory}</weaveDirectory>

在Maven编译器插件编译之后,将其附加到编译阶段。这样,将首先调用Lombok+Javac,然后AJC将对生成的Java类文件执行编织。

在javac生成的类上执行字节码编织有什么限制/缺点吗?

也许有一种更好的方法可以让Maven+Lombok+Aspects+IDEA协同工作,而不会出现问题。

这里有一个最小的示例项目:https://github.com/Psimage/aspectj-and-lombok


解决方案

当您在另一个问题的评论中问我时,我实际上认为您的方法有问题,但它是有效的。为了直接从IDE(IntelliJ IDEA)运行测试,我必须做的唯一一件事就是将应用程序和测试运行者实际委托给Maven,否则IDEA不会同时应用Lombok+AspectJ。

如果您的方法有效,请使用它。但实际上AspectJ Maven建议another approach:首先使用Maven编译器编译到另一个输出目录,然后将该目录用作AspectJ编译器的编织目录。不过,示例POM并不能100%正常工作,因为当在命令行中为Javac指定输出目录时,该目录需要存在,编译器不会创建该目录。因此,您还需要一些丑陋的Antrun动作:

<plugins>

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
      <execution>
        <id>unwovenClassesFolder</id>
        <phase>generate-resources</phase>
        <configuration>
          <tasks>
            <delete dir="${project.build.directory}/unwoven-classes"/>
            <mkdir dir="${project.build.directory}/unwoven-classes"/>
          </tasks>
        </configuration>
        <goals>
          <goal>run</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <executions>
      <execution>
        <!-- Modifying output directory of default compile because non-weaved classes must be stored
             in separate folder to not confuse ajc by reweaving already woven classes (which leads to
             to ajc error message like "bad weaverState.Kind: -115") -->
        <id>default-compile</id>
        <configuration>
          <compilerArgs>
            <arg>-d</arg>
            <arg>${project.build.directory}/unwoven-classes</arg>
          </compilerArgs>
        </configuration>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <configuration>
      <aspectLibraries>
        <aspectLibrary>
          <groupId>me.yarosbug</groupId>
          <artifactId>aspects</artifactId>
        </aspectLibrary>
      </aspectLibraries>

      <forceAjcCompile>true</forceAjcCompile>
      <sources/>
      <weaveDirectories>
        <weaveDirectory>${project.build.directory}/unwoven-classes</weaveDirectory>
      </weaveDirectories>
    </configuration>
    <executions>
      <execution>
        <phase>process-classes</phase>
        <goals>
          <goal>compile</goal>
        </goals>
      </execution>
    </executions>
  </plugin>

  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
  </plugin>

</plugins>

我建议使用另一种方法作为替代:

  1. 创建未编织的Java模块,在那里执行Java+Lombok操作。
  2. 使用Java模块作为编织依赖项,为AspectJ二进制编织创建一个单独的模块。因为您的单元测试同时依赖于Lombok和AspectJ,所以将测试放在此模块中。

这样做的好处是,您不需要纠结于多个编译器、执行阶段、输出目录、Antrun等。


更新:

我克隆了您的GitHubMCVE和this commit on branch master反映了我在上面的示例XML中解释的内容。

我还创建了branch multi-phase-compilation和another commit,它根据我的替代想法有效地重构了项目。我只是引用提交消息:

Multi-phase compilation: 1. Java + Lombok, 2. AspectJ binary weaving

There are many changes (sorry, I should have split them into multiple
commits):
  - Marker annotation renamed to @marker and moved to separate module
    because the main application should not depend on the aspect module.
    Rather both application and aspect now depend on a common module.
  - New module "main-app-aspectj" does only AspectJ binary weaving on
    the already lomboked Java application.
  - Both application modules have slightly different unit tests now: One
    checks that Lombok has been applied and AspectJ has not, the other
    checks that both have been applied.
  - Aspect pointcut limits matching to "execution(* *(..))" in order to
    avoid also matching "call()" joinpoints.

The end result is that now we have a clear separation of concerns, clear
dependencies, no more scripted Ant build components and the new option
to use the lomboked code optionally with or without aspects applied
because both types or JARs are created during the build.
请随意将我的fork作为另一个遥控器添加到您的Git存储库,并从那里获取我的更改。如果您希望我向您发送拉取请求以使操作更轻松,请让我知道。

相关文章