Maven:编译包含Java 1.6源代码的AspectJ项目

22

主要问题

我想做的事情很简单。或者你会这样认为。然而,没有什么是正常工作的。

需求: 使用Maven编译Java 1.6项目,使用AspectJ编译器。

注意: 我们的代码无法使用javac编译。也就是说,如果没有编织方面(因为我们有使异常变得软化的方面),它将无法通过编译。


更新2/21/2011: 对此有两个同样可行的解决方案(两种情况都使用aspectj-maven-pluginmaven-compiler-plugin):

  1. 在编译器插件中添加 <failOnError>false</failOnError> (感谢 Pascal Thivent
  2. 在AspectJ编译器插件中添加<phase>process-sources</phase> (感谢Andrew Swan

有关这些解决方案的更多信息请参见答案部分。我认为第二种解决方案是更好的方法。







相关问题

问题(基于下面的失败尝试):

  1. 如何让maven直接运行aspectj:compile目标,而不运行compile:compile?
  2. 如何忽略compile:compile的失败?
  3. 如何指定自定义的compilerId,该compilerId指向您自己的ajc编译器(也就是说,使compile:compile使用除plexus以外的其他AspectJ编译器)?*
感谢所有意见和建议。以下是我尝试过的导致我的问题/问题的事情:


尝试1(失败): 将AspectJ指定为maven-compiler-plugin的编译器:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.2</version>
<configuration>
 <source>1.6</source>
 <target>1.6</target>
 <compilerId>aspectj</compilerId>
</configuration>
<dependencies>
 <dependency>
  <groupId>org.codehaus.plexus</groupId>
  <artifactId>plexus-compiler-aspectj</artifactId>
  <version>1.8</version>
 </dependency>
</dependencies>
</plugin>

以下内容会导致错误:

org.codehaus.plexus.compiler.CompilerException: The source version was not recognized: 1.6

无论我使用哪个版本的plexus编译器(1.8、1.6、1.3等),都不起作用。我实际上浏览了源代码,并发现这个编译器不支持Java 1.5以上的源代码。

尝试2(失败): 在编译和测试编译目标中使用aspectJ-maven-plugin插件:

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
 <source>1.6</source>
 <target>1.6</target>
</configuration>
<executions>
 <execution>
  <goals>
   <goal>compile</goal>      
   <goal>test-compile</goal> 
  </goals>
 </execution>
</executions>
</plugin>

无论是运行以下命令:

mvn clean test-compile
mvn clean compile

都会失败,因为它尝试在运行aspectj:compile之前执行compile:compile。如上所述,我们的代码不需要使用javac编译,而是需要使用aspects。因此,mvn需要完全跳过compile:compile目标,并仅运行aspectj:compile。

尝试3(可行但不可接受):

使用与上面相同的配置,但运行以下命令:

mvn clean aspectj:compile

这个方法有效,可以成功构建,但它是不可接受的,因为我们需要能够直接运行compile目标和test-compile目标(m2eclipse自动构建取决于这些目标)。此外,以这种方式运行需要我们逐个列出每个目标(例如,我们需要分发资源并运行测试并部署测试资源等)。


参见:https://stackoverflow.com/a/16248351/59087 - Dave Jarvis
4个回答

16

AspectJ插件的版本1.3故意将其编译目标的默认阶段从 process-sources 改为 compile,请参见 MASPECTJ-13。这会导致像你遇到的问题或者 MASPECTJ-92 等后续问题。要恢复在 javac 之前运行 ajc 的以前行为,只需要在相关的“execution”标记中添加一个“phase”标记,例如:

<execution>
    <phase>process-sources</phase> <!-- or any phase before compile -->
    <goals>
        <goal>compile</goal>
        <goal>test-compile</goal>
    </goals>
</execution>

2
感谢您的发布!虽然我是一年前发布这个问题的人,而且我已经远离了原始问题所在的项目(我们已经从Maven转换到了Ivy!),但我认为您的解决方案可能有效。等我有机会时,我会建立一个测试环境并尝试一下! - gMale
3
你的方案完美地解决了问题。我也看了你提供链接中的讨论,我倾向于同意你的观点,他们所做的更改似乎比有帮助更为棘手。起初,我认为将过程绑定到"process-sources"阶段有些"hack",但经过深思熟虑,这样做是很有道理的——AspectJ在编译之前编织源代码!我正在更改我的采纳答案,因为我认为这是一个更好的方法。 - gMale

4
如何让maven-compiler-plugin跳过所有*.java文件,让aspectj-maven-plugin来完成工作呢?
...
<build>
  <plugins>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>2.0.2</version>
      <configuration>
        <excludes>
          <exclude>**/*.java</exclude>
        </excludes>
      </configuration>
    </plugin>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>aspectj-maven-plugin</artifactId>
      <version>1.3</version>
      <configuration>
        <source>1.6</source>
        <target>1.6</target>
        <encoding>utf-8</encoding>
        <complianceLevel>1.6</complianceLevel>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>       <!-- weave main classes -->
            <goal>test-compile</goal>  <!-- weave test classes -->
          </goals>
        </execution>
       </executions>
    </plugin>
  </plugins>
</build>

我有一段时间没有看过这个问题了,但我认为你在这里写的是一个非常好的选项,可能会完全解决它。我必须测试一下,以确保调用“mvn compile”仍然会调用aspectj编译器。此外,我还需要检查从编译器插件中排除java文件是否间接地将它们从aspectJ编译中排除。我们目前正在项目的另一个领域工作,但下次我打开中间件代码时,我会测试你的建议。谢谢!我认为它会起作用。 - gMale
我在我的Maven模块中尝试了它,而且它起作用了。虽然最终因为其他原因放弃了排除这样的东西。我的项目使用国家字符,而aspectj-maven-plugin似乎会搞乱编码。所以最后我重构了模块,使得Java中没有对AJ的引用。Javac编译.java文件,之后AspectJ编译缺失的.aj文件。到目前为止都很顺利。 - Tomasz Domzal
你尝试过将插件的“编码”选项设置为所需的值吗?请参见http://mojo.codehaus.org/aspectj-maven-plugin/apidocs/org/codehaus/mojo/aspectj/AbstractAjcCompiler.html#encoding - Andrew Swan
@gmale:“mvn compile”调用编译阶段,首先调用“maven-compiler-plugin”插件的“compile”目标,然后调用绑定到该阶段的任何其他插件的目标(默认情况下包括aspectj-maven-plugin的编译和测试编译目标),因此是的,它仍将调用AspectJ编译器,除非您将“phase”标签添加到该插件的“execution”标签以将其绑定到不同的阶段。 - Andrew Swan

2

我在一个项目中使用了这个配置来通过Maven编译AspectJ和Java 6:

<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.6.8</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.0.2</version>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.3</version>
            <configuration>
                <complianceLevel>1.6</complianceLevel>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>  
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Ref: aspectj-maven-plugin


1
compiler:compile之前不会调用aspectj:compile - Pascal Thivent
你的 complianaceLevel 是 1.6。这是我尚未尝试过的唯一事情,但正如 Pascal 所提到的,我不认为这会解决我的问题,因为 compile:compile 仍然会首先发生。我想知道是否有一种方法可以忽略 compile:compile 的失败... 嗯,我会在上面的问题中添加这个。 - gMale
如果您关闭IDE(排除自动构建)并执行“mvn clean”后跟着“mvn install”,这是否有效?而且您的项目如何打包?我的EAR项目与您的类似,但无法编译。您的Java代码是否依赖于AspectJ代码,例如调用ITD引入的任何方法? - Andrew Swan

1
你如何指定一个自定义的编译器ID,指向你自己的ajc编译器(即使编译使用的是除了Plexus之外的AspectJ编译器)?
我不知道如何指定除"官方"之外的其他compilerId。不确定是否可能。
我的理解是http://jira.codehaus.org/browse/MCOMPILER-107可以解决你的问题(AspectJ 1.6+是否支持Java 1.6?)。可惜,它仍然是开放状态。
你如何忽略compile:compile的失败?

Maven Compiler plugincompiler:compile 目标有一个可选参数 failOnError,允许指示即使存在编译错误,构建是否将继续

<project>
  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.2</version>
        <configuration>
          <failOnError>false</failOnError>
          ...
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

这可能是解决上述问题的一个丑陋的解决方法。

如何让Maven直接运行aspectj:compile目标,而不运行compile:compile?

问题在于compiler:compile绑定到compile阶段,而你无法删除默认生命周期绑定。因此,也许还有另一种选择,但我能想到的唯一选择是通过使用<packaging>pom<packaging>关闭所有内容,并手动重新绑定所有目标(至少对于这些阶段:process-resourcescompileprocess-test-resourcestest-compiletestpackage)。简单来说,就像这样:

process-resources       资源:资源
compile                 aspectj:编译
process-test-resources  资源:测试资源
test-compile            编译器:测试编译
test                    surefire:测试
package                 ejb:ejb 或 ejb3:ejb3 或 jar:jar 或 par:par 或 rar:rar 或 war:war
install                 安装:安装
deploy                  部署:部署

这可能是另一个丑陋的解决方法。免责声明:未经测试但应该有效。


是的。那真的很烦人。我应该能够说“compile:compile”被替换为“aspectJ:compile”。我可以通过<compilerId>设置有点做到这一点。唯一的问题是,当我将“aspectJ”命名为compilerId时,它使用不支持Java 1.6的Plexus版本,而不是AspectJ插件。我不知道你可以通过pom打包完全重新定义阶段!这是非常好的信息,+1!当然,在这样做之前,我会使用上面的解决方案#3,并在我的Eclipse运行配置中列出所有目标。我只是想知道所谓的“约定”是什么来解决这个问题。 - gMale
非常感谢您的额外帮助。今天我有更多时间后,我会投票支持那个Codehaus bug。很遗憾他们的默认Aspect编译器不支持Java 1.6,而Java 1.6已经发布了3年之久!今天晚些时候,我可能会尝试failOnError解决方法,因为由于javac编译器将柔化的异常视为未检查异常,所以编译很快且安静地失败。这似乎是所有恶行中较小的一种,并且可能是Codehaus / Java1.6问题的“官方”解决方法。 - gMale
当代码没有被编织时,这只是一个问题。然而,在使用AspectJ时,这种情况经常发生。 - gMale
@gmale 是的,我理解了。但这确实是一个非常有效的用例。 - Pascal Thivent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接