为什么aspectj将我的测试文件夹中的Aspects编织到我的源类中(而不是测试类)?

时间:2015-06-16 20:20:57

标签: java eclipse maven unit-testing aspectj

我遇到了与aspectj-maven-plugin和Eclipse Juno的奇怪问题。我在我的pom的构建部分中有以下插件定义:

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.7</version>
            <configuration>
                <showWeaveInfo>true</showWeaveInfo>
                <source>1.7</source>
                <target>1.7</target>
                <Xlint>ignore</Xlint>
                <complianceLevel>1.7</complianceLevel>
                <encoding>UTF-8</encoding>
                <verbose>true</verbose>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <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>

我在src / test / java / ...文件夹中声明了@Aspect

如果我是从命令行构建的(即:mvn clean package),我的类是按照预期正确构建的。

但是,当我在Eclipse中构建时,在我的测试文件夹中声明的方面被编织到我的输出类文件夹.class文件中,而不是test-classes文件夹(通过使用反编译器确认)。

我的配置不正确吗?我的Eclipse项目中是否缺少一个设置来指示在编译时忽略方面?如果我在Eclipse中检查我的Java Build path配置,我会看到src / main / java - &gt;目标/类,而src / test / java-&gt;目标/测试类。

这可能与配置的生命周期映射有关吗? 我有:

Plugin Extension          Mapping                      Source
aspectj:compile           configurator                extension
aspectj:test-compile      configurator                extension

我安装了AJDT 1.7.3(org.aspectj)和2.2.3(org.eclipse.ajdt)(我不确定为什么安装了这两个版本)。

更新2

我将Aspectj-maven-plugin配置更新为以下内容并覆盖m2e连接器设置并且它似乎有效,但我希望第三方验证如果这适用于其他人,因为它似乎是编辑器/配置依赖。

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.7</version>
            <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>
            <executions>
                <execution>
                    <id>compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                    <sources>
                        <source>
                            <basedir>${project.build.sourceDirectory}</basedir>
                            <includes>
                                <include>**/*.aj</include>
                                <include>**/*.java</include>
                            </includes>
                        </source>
                    </sources>
                    </configuration>
                </execution>
                <execution>
                    <id>test compile</id>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>
                                <basedir>${project.build.testSourceDirectory}</basedir>
                                <includes>
                                    <include>**/*.aj</include>
                                    <include>**/*.java</include>
                                </includes>
                            </source>
                        </sources>
                        <weaveDirectories>
                            <param>${project.build.outputDirectory}</param>
                        </weaveDirectories>
                    </configuration>
                </execution>
            </executions>
            <configuration>
                <verbose>true</verbose>
                <outxml>true</outxml>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <complianceLevel>${java.version}</complianceLevel>
                <showWeaveInfo>true</showWeaveInfo>
            </configuration>
        </plugin>

使用以下m2e配置覆盖AJDT / m2e 0.14框架附带的m2e连接器设置:                                                            org.eclipse.m2e                     生命周期映射                     1.0.0                                                                                                                                                                                                                                       org.codehaus.mojo                                                                                                                               AspectJ的Maven的插件                                                                                                                               [1.7,)                                                                                                                               编                                                                                                                                                                                                                                                                                                                                                                                              org.codehaus.mojo                                                                                                                               AspectJ的Maven的插件                                                                                                                               [1.7,)                                                                                                                               测试编译                                                                                                                                                                                                                                                                                                                                                    

如果这对其他人有用,下一步是尝试了解m2e连接器如何/为何失败,以及需要修复的位置。

我将测试代码(包括@kriegaex测试项目)上传到我的github示例项目:github.com/benze/aspectj-maven-plugin-defect-example.git。根据自述文件,要启用/禁用覆盖m2e-connector,请启用override-m2e-lifecycle配置文件。

1 个答案:

答案 0 :(得分:1)

我刚刚尝试在AspectJ users mailing list上回答您的问题,并在此处找到了相同的问题。至于这一部分,......

  

我安装了AJDT 1.7.3(org.aspectj)和2.2.3(org.eclipse.ajdt)(我不确定为什么安装了这两个版本)。

前者似乎适用于实际的AspectJ(编译器和运行时)版本,在我的Eclipse Luna中它是1.8.5。后者适用于AJDT插件组件,在我的IDE中它是2.2.4。

<强>更新

你关于M2Eclipse生命周期映射的假设(另见你的new mailing list post) - 这是我以前从未听说过的,但只是第一次调查 - 是其中的根本原因问题似乎是真的。

抱歉,这不起作用,请参阅下面的更新2.

阅读this并查看我安装的m2e插件中的默认生命周期映射

<eclipse-dir>/plugins/org.eclipse.m2e.lifecyclemapping.defaults_1.5.0.20140606-0033.jar
    -> lifecycle-mapping-metadata.xml

我意识到AspectJ Maven插件没有默认映射。所以我刚创建了一个菜单选项

Window -> Preferences
    Maven -> Lifecycle Mappings

Eclipse m2e lifecycle mappings menu

具有以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<lifecycleMappingMetadata>
    <pluginExecution>
      <pluginExecutionFilter>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <versionRange>[1.0,)</versionRange>
        <goals>
          <goal>compile</goal>
          <goal>test-compile</goal>
        </goals>
      </pluginExecutionFilter>
      <action>
        <execute>
          <runOnIncremental>true</runOnIncremental>
        </execute>
      </action>
    </pluginExecution>
  </pluginExecutions>
</lifecycleMappingMetadata>

这解决了我在Eclipse安装中的问题(我可以在我自己的小型演示项目中重现)。

我认为从M2Eclipse中提供AspectJ Maven插件的默认映射(有人应该打开票证,我猜)或者甚至直接在AspectJ Maven插件中通过在插件中提供默认映射工具来提供默认映射(其中根据M2E文件据说是可能的。)

这是我的示例项目:

Maven项目POM:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.scrum-master.aspectj</groupId>
    <artifactId>unit-test-specific-aspect</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <aspectj.version>1.8.6</aspectj.version>
    </properties>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <!-- IMPORTANT -->
                    <useIncrementalCompilation>false</useIncrementalCompilation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <showWeaveInfo>true</showWeaveInfo>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>${java.version}</complianceLevel>
                    <encoding>UTF-8</encoding>
                    <verbose>true</verbose>
                </configuration>
                <executions>
                    <execution>
                        <id>compile</id>
                        <!-- IMPORTANT -->
                        <phase>process-sources</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <!-- IMPORTANT -->
                        <phase>process-sources</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                        <configuration>
                            <weaveDirectories>
                                <param>${project.build.outputDirectory}</param>
                            </weaveDirectories>
                        </configuration>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>${aspectj.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.3</version>
                <configuration>
                    <mainClass>de.scrum_master.app.Application</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${aspectj.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

驱动程序应用程序:

package de.scrum_master.app;

public class Application {
    public static void main(String... args) {
        System.out.println("Hello world!");
    }
}

单元测试:

package de.scrum_master.app;

import org.junit.Test;

import static org.junit.Assert.*;

public class ApplicationTest {
    @Test
    public void testMain() throws Exception {
        Application.main("foo");
    }

    @Test
    public void testOne() throws Exception {
        System.out.println("Test one");
    }

    @Test
    public void testTwo() throws Exception {
        System.out.println("Test two");
    }
}

测试方面(位于 src / test / java ):

package de.scrum_master.app;

public aspect TestAspect {
    before() : execution(* *(..)) {
        System.out.println(thisJoinPoint);
    }
}

mvn clean package exec:java的控制台输出:

[INFO] ------------------------------------------------------------------------
[INFO] Building unit-test-specific-aspect 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------

(...)

[INFO] --- aspectj-maven-plugin:1.7:compile (compile) @ unit-test-specific-aspect ---
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] 
[INFO] --- aspectj-maven-plugin:1.7:test-compile (test-compile) @ unit-test-specific-aspect ---
[INFO] Showing AJC message detail for messages of types: [error, warning, fail]
[INFO] Join point 'method-execution(void de.scrum_master.app.Application.main(java.lang.String[]))' in Type 'de.scrum_master.app.Application' (Application.java:4) advised by before advice from 'de.scrum_master.app.TestAspect' (TestAspect.aj:4)
[INFO] Join point 'method-execution(void de.scrum_master.app.ApplicationTest.testMain())' in Type 'de.scrum_master.app.ApplicationTest' (ApplicationTest.java:9) advised by before advice from 'de.scrum_master.app.TestAspect' (TestAspect.aj:4)
[INFO] Join point 'method-execution(void de.scrum_master.app.ApplicationTest.testOne())' in Type 'de.scrum_master.app.ApplicationTest' (ApplicationTest.java:14) advised by before advice from 'de.scrum_master.app.TestAspect' (TestAspect.aj:4)
[INFO] Join point 'method-execution(void de.scrum_master.app.ApplicationTest.testTwo())' in Type 'de.scrum_master.app.ApplicationTest' (ApplicationTest.java:19) advised by before advice from 'de.scrum_master.app.TestAspect' (TestAspect.aj:4)

(...)

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running de.scrum_master.app.ApplicationTest
execution(void de.scrum_master.app.ApplicationTest.testOne())
Test one
execution(void de.scrum_master.app.ApplicationTest.testTwo())
Test two
execution(void de.scrum_master.app.ApplicationTest.testMain())
execution(void de.scrum_master.app.Application.main(String[]))
Hello world!

(...)

[INFO] --- exec-maven-plugin:1.3:java (default-cli) @ unit-test-specific-aspect ---
[WARNING] Warning: killAfter is now deprecated. Do you need it ? Please comment on MEXEC-6.
Hello world!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

(...)

所以它在Maven中起作用,就像之前一样。但是如何通过正常运行配置从Eclipse运行代码呢?

Hello world!

没有方面,很酷!那么Eclipse中的单元测试呢?

execution(void de.scrum_master.app.ApplicationTest.testOne())
Test one
execution(void de.scrum_master.app.ApplicationTest.testTwo())
Test two
execution(void de.scrum_master.app.ApplicationTest.testMain())
execution(void de.scrum_master.app.Application.main(String[]))
Hello world!

Tadaa,方面被编织成Application.main。 Eclipse和Maven都可以按照我们的要求运行。

更新2:

我很抱歉,它只是起作用,因为我在Maven构建之后没有完成完整的Eclipse重建。显然,生命周期映射还不够,甚至可能不是解决方案的正确途径。我想,Eclipse只是不知道AspectJ Maven插件中的<weaveDirectories>设置,这是一件非常重要的事情。