简体   繁体   English

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

[英]How to use AspectJ Maven for binary weaving after Javac + Lombok phase

I have a project that uses compiled aspects and weaves them at compile time. 我有一个使用已编译方面并在编译时进行编织的项目。 I want to add Lombok, but unfortunately AJC is not supported by Lombok. 我想添加Lombok,但是不幸的是Lombok不支持AJC。 Since this project doesn't have any sources of aspects on its own i configured AspectJ Maven plugin to do post-compile weaving instead, after compiling with Javac+Lombok. 由于该项目本身没有任何方面的资源,因此在使用Javac + Lombok进行编译后,我将AspectJ Maven插件配置为进行后编译编织。

Here is config for AspectJ Maven plugin: 这是AspectJ Maven插件的配置:

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

It's attached to compile phase right after Maven Compiler plugin compile. 它在Maven Compiler插件编译之后立即附加到编译阶段。 That way Lombok + Javac will be invoked first and later AJC will perform weaving on Javac's generated class files. 这样,将首先调用Lombok + Javac,随后AJC将对Javac生成的类文件执行编织。

Is there any limitations/disadvantages when performing bytecode weaving on javac generated classes? 在javac生成的类上执行字节码编织时,是否有任何限制/缺点?

Maybe there is a better approach of making Maven+Lombok+Aspects+Idea work together without issues. 也许有更好的方法可以使Maven + Lombok + Aspects + Idea一起工作而不会出现问题。

Here is a minimal example project: https://github.com/Psimage/aspectj-and-lombok 这是一个最小的示例项目: https : //github.com/Psimage/aspectj-and-lombok

When in the other question you asked me in a comment I actually thought that you had problems with your approach, but it is working. 在另一个问题中,当您在评论中问我时,我实际上以为您的方法有问题,但它是有效的。 The only thing I had to do in order to run the test directly from IDE (IntelliJ IDEA) is to actually delegate application and test runners to Maven because otherwise IDEA does not get Lombok + AspectJ applied at the same time. 为了直接从IDE(IntelliJ IDEA)直接运行测试,我要做的唯一一件事就是实际上将应用程序和测试运行程序委托给Maven,因为否则IDEA不会同时应用Lombok + AspectJ。

将IDE构建/运行操作委托给Maven

If your approach works, use it. 如果您的方法可行,请使用它。 But actually AspectJ Maven suggests another approach : compiling with Maven compiler first to another output directory, then use that directory as weave directory for the AspectJ compiler. 但是实际上AspectJ Maven建议使用另一种方法 :首先使用Maven编译器编译到另一个输出目录,然后将该目录用作AspectJ编译器的编织目录。 The sample POM there does not work 100%, though, because when specifying an output directory for Javac on the command line that directory needs to exist, it will not be created by the compiler. 但是,这里的示例POM无法100%工作,因为在命令行上为Javac指定输出目录时,该目录需要存在,编译器不会创建该目录。 So you need some ugly Antrun action, too: 因此,您还需要执行一些丑陋的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>

I would suggest another approach as an alternative: 我建议另一种方法作为替代:

  1. Create an unwoven Java module, doing Java + Lombok stuff there. 创建一个非编织的Java模块,在那里执行Java + Lombok的工作。
  2. Create a separate module for AspectJ binary weaving, using the Java module as a weave dependency. 使用Java模块作为编织依赖项,为AspectJ二进制编织创建一个单独的模块。 Because your unit test depends on both Lombok and AspectJ, put the test in this module. 因为您的单元测试取决于Lombok和AspectJ,所以将测试放入此模块中。

The advantage is that you don't need to fiddle around with multiple compilers, execution phases, output directories, Antrun etc. 优点是您无需费心处理多个编译器,执行阶段,输出目录,Antrun等。


Update: 更新:

I cloned your GitHub MCVE and this commit on branch master reflects what I have explained in my sample XML above. 我克隆了您的GitHub MCVE对分支主站的此提交反映了我在上面的示例XML中所解释的内容。

I also created a branch multi-phase-compilation with another commit which effectively refactors the project according to my alternative idea. 我还用另一个提交创建了一个分支多阶段编译 ,它根据我的替代想法有效地重构了项目。 I am just quoting the commit message: 我只是引用提交消息:

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.

Feel free to add my fork as another remote to your Git repository and pull in my changes from there. 随意将我的fork作为另一个远程添加到您的Git存储库,并从那里提取我的更改。 If you prefer me to send you pull requests in order to make it easier, just let me know. 如果您希望我发送拉取请求以便于您轻松进行,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM