【问题标题】:How to use AspectJ Maven for binary weaving after Javac + Lombok phaseJavac + Lombok阶段后如何使用AspectJ Maven进行二进制编织
【发布时间】:2019-11-21 13:59:07
【问题描述】:

我有一个项目使用编译的方面并在编译时编织它们。我想添加 Lombok,但不幸的是 Lombok 不支持 AJC。由于这个项目本身没有任何方面的来源,我在使用 Javac+Lombok 编译后配置了 AspectJ Maven 插件来进行编译后编织。

这是 AspectJ Maven 插件的配置:

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

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

在 javac 生成的类上执行字节码编织时是否有任何限制/缺点?

也许有更好的方法可以让 Maven+Lombok+Aspects+Idea 一起工作而不会出现问题。

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

【问题讨论】:

    标签: java maven aspectj lombok aspectj-maven-plugin


    【解决方案1】:

    当你在评论中问我另一个问题时,我实际上认为你的方法有问题,但它确实有效。为了直接从 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. 为 AspectJ 二进制编织创建一个单独的模块,使用 Java 模块作为编织依赖项。因为您的单元测试同时依赖于 Lombok 和 AspectJ,所以将测试放在这个模块中。

    优点是您不需要摆弄多个编译器、执行阶段、输出目录、Antrun 等。


    更新:

    我克隆了你的 GitHub MCVEthis commit on branch master 反映了我在上面的示例 XML 中解释的内容。

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

    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 存储库,并从那里提取我的更改。如果您希望我向您发送拉取请求以使其更容易,请告诉我。

    【讨论】:

    • 请注意,我已经用额外的信息和资源更新了我的答案。
    • 为了让 IDEA 运行我的项目,我所做的是确保在 Java compiler 设置中设置了 Delegate to javac,并且 main-app 模块的 aspectj 方面启用了 post-compile weave mode 选项(它没有重置在 Maven 项目重新导入上)。感谢您让我知道委托给 Maven 选项。从来不知道。
    • 我查看了您链接的官方方法,但编译时 ajc 没有问题,所以我没有更改目录。而且似乎没有必要绑定到进程类。
    • 感谢您花时间玩这个示例项目。不幸的是,我不能在实际应用中使用您的 multi-phase-compilation 方法。我想将 Lombok 添加到一个有很多事情的旧项目中,但是添加 Lombok 会改变生成的字节码(将 ajc 更改为 javac+binary ajc)。转向编译后编织是否有任何风险?
    • 这个问题很笼统。什么样的风险以及与什么相比?没有我能想到的会阻止我使用它。此外,您刚才对我所说的遗留应用程序听起来不像我的两阶段方法行不通。 BTW,如果你想直接用Ajc编译Java代码,可以考虑先用Delombok via Maven plugin再正常编译。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    • 2014-10-02
    • 1970-01-01
    相关资源
    最近更新 更多