【问题标题】:Weaving production classes with AspectJ aspects in Maven for tests execution only在 Maven 中使用 AspectJ 方面编织生产类,仅用于测试执行
【发布时间】:2010-09-27 14:46:30
【问题描述】:

我有一个使用 Maven 构建的项目,需要向方法添加一些基本的性能跟踪。我决定为此使用 AspectJ。主要要求是将跟踪方面编织到生产类中但仅适用于单元测试执行阶段

我能够在 Maven 中配置编织,但是在执行测试后,应用了方面的相同生产类转到打包战争。

这个案例看起来很常见,但我无法在网络上找到解决方案。

【问题讨论】:

    标签: java maven-2 maven aspectj


    【解决方案1】:

    你可以把你的方面放在测试目录中,并在测试编译配置中将 weaveMainSourceFolder 标志设置为 true

    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.4</version>
        <configuration>
            <showWeaveInfo>true</showWeaveInfo>
            <source>1.7</source>
            <target>1.7</target>
        </configuration>
            <executions>
                <execution>
                    <id>test-compile</id>
                    <configuration>
                        <weaveMainSourceFolder>true</weaveMainSourceFolder>
                    </configuration>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjtools</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
        </dependencies>
    </plugin>
    

    http://mojo.codehaus.org/aspectj-maven-plugin/test-compile-mojo.html

    【讨论】:

    • 那么,这是否会导致您打包的 jar 没有编织版本?这对我有用,因为我的测试现在可以工作,但从表面上看,我为主要源文件打包的 JAR 文件现在似乎是编织版本。或者,它是否为测试或其他东西制作了单独的副本?在制作我的包的最终版本时是否需要跳过测试?
    • 回答我之前评论中的问题:是的,这种方法导致主要来源被编织到您的生产版本中。我通过更改为加载时编织解决了这个问题,这可能是仅在测试运行期间使用编织的最佳方式。
    【解决方案2】:

    我通过加载时编织解决了这个问题。这样,在运行单元测试时会发生编织(在运行单元测试时通过命令行参数),但您的方面不会编织到已发布的工件中。

    例如,我想在我的单元测试中伪造系统时钟,但显然不会在实时代码中弄乱它。这是我的方面类:

    @Aspect
    public class TweakSystemAspects {
        private static long timeOffsetMillis = 0;
    
        public static void advanceTime(int amount, TimeUnit unit) {
            timeOffsetMillis += unit.toMillis(amount);
        }
    
        @Around("call (long System.currentTimeMillis())")
        public long aroundSystemTime(ProceedingJoinPoint joinPoint) throws Throwable {
            return ((Long) joinPoint.proceed()) + timeOffsetMillis;
        }
    }
    

    显然,这是通过调用TweakSystemAspects.advanceTime() 方法在单元测试中使用的,以伪造系统中的时间流逝。为了完成加载时间编织,我只需要创建一个定义我的方面的 aop.xml 文件(并且编织应该发生在所有类中):

    <aspectj>
        <aspects>
            <aspect name="com.mypackage.TweakSystemAspects"/>
        </aspects>
        <weaver options="-nowarn -Xlint:ignore"/>
        <!-- During testing this was useful, but I didn't want all that output normally. -->
        <!--<weaver options="-verbose -showWeaveInfo"/>-->
    </aspectj>
    

    最后,我在我的 pom 文件中进行了更改,以声明 AspectJ 运行时依赖项并告诉 Surefire 进行运行时编织。

    <project ...>
        ...
        <properties>
            ...
            <version.aspectj>1.8.10</version.aspectj>
        <properties>
    
        <dependencies>
            ...
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${version.aspectj}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                ...
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <configuration>
                        <!-- For Load Time Weaving of our AspectJ helper code -->
                        <argLine>-javaagent:${settings.localRepository}/org/aspectj/aspectjweaver/${version.aspectj}/aspectjweaver-${version.aspectj}.jar</argLine>
                        ...
                    </configuration>
                </plugin>
            </plugins>
        </build>
        ...
    </project>
    

    【讨论】:

      【解决方案3】:

      我会在专用模块中执行此操作,在 generate-test-sources 阶段使用 Maven 依赖插件解压缩“正在测试”的工件,然后编织类并最终运行测试。


      让我试着说明我的意思。让我们想象一下下面的项目结构:

      . |-- pom.xml `-- some-module // 这是我们要编织的模块 |-- pom.xml // 但仅用于测试目的 `-- ...

      所以我的建议是这样做:

      . |-- pom.xml |-- 一些模块 | |-- pom.xml | `-- ... `-- test-module // 我们将在这里编织类,因为我们不想要 |-- pom.xml // 要打包在“生产”jar 中的跟踪方面 `-- ...

      我们的想法是有一个额外的“测试模块”,我们可以在其中解压缩我们想要测试的工件,以便我们可以在不影响“真实”生产 jar 的情况下编织它的类。

      为此,请声明对被测模块的依赖关系并使用dependency:unpack 将类解压到target/classes,然后调用AspectJ 插件来编织“主”类。

      【讨论】:

      • 帕斯卡,谢谢你的回答。但是我不确定我明白你的意思。让我试着澄清一下。
      • 您提议将生产代码放入单独的 Maven 模块中,并且根本不将测试放在那里。然后主项目将仅包含测试。在 process-test-classes (我假设这是您的意思的阶段),它会将生产类从单独的模块解压缩到测试类文件夹并将方面编织到它们中。然后它将运行测试。这种理解正确吗?
      • 帕斯卡,我想我现在明白了。我会尝试建议的方法并让您知道结果。
      【解决方案4】:

      根据AspectJ compiler Maven Plugin - Usage 中提供的示例,应该可以使用以下内容:

      <project>
          ...
          <build>
              <plugins>
                  ...
                  <plugin>
                      <groupId>org.codehaus.mojo</groupId>
                      <artifactId>aspectj-maven-plugin</artifactId>
                      <executions>
                          <execution>
                              <goals>
                                  <goal>test-compile</goal>
                              </goals>
                          </execution>
                     </executions>
                 </plugin>
                 ...
             </plugins>
         <build>
         ...
      </project>
      

      【讨论】:

      • 这将编织测试类,这不是 OP 想要的。 OP 想要编织“主”类,但仅用于测试目的(跟踪方面不应包含在打包的类中)。
      • 帕斯卡,你是对的。 AspectJ maven 插件的问题在于它将生产方面编织到生产类中,并将测试方面编织到测试类中,但我需要“混合”它们。
      • 投反对票,因为这根本不能解决 OP 问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多