简体   繁体   English

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

[英]Why is aspectj weaving Aspects from my test folder into my source classes (as opposed to the test classes)?

I'm running into a strange problem with aspectj-maven-plugin and Eclipse Juno.我遇到了aspectj-maven-plugin 和Eclipse Juno 的一个奇怪问题。 I have the following plugin defn in the build section of my pom:我的 pom 的构建部分中有以下插件 defn:

        <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>

I have an @Aspect declared in my src/test/java/... folder.我在 src/test/java/... 文件夹中声明了一个@Aspect

If I build from the command line (ie: mvn clean package), my classes are built properly/as expected.如果我从命令行构建(即:mvn clean package),我的类就会正确构建/按预期构建。

However, when I build from within Eclipse, the aspect declared in my test folder is woven into my output classes folder .class file as opposed to the test-classes folder (as confirmed by using a decompiler).但是,当我从 Eclipse 中构建时,在我的 test 文件夹中声明的方面被编织到我的输出类文件夹 .class 文件中,而不是 test-classes 文件夹(通过使用反编译器确认)。

Is my configuration incorrect?我的配置不正确吗? Is there a setup I am missing in my Eclipse project to indicate to ignore the aspects when compiling?我的 Eclipse 项目中是否缺少一个设置来指示在编译时忽略方面? If I check my Java Build path config in Eclipse, I see that src/main/java -> target/classes whereas src/test/java-> target/test-classes.如果我在 Eclipse 中检查我的 Java Build 路径配置,我会看到 src/main/java -> target/classes 而 src/test/java-> target/test-classes。

Might this have something to do with the Lifecycle Mapping that is configured?这可能与配置的生命周期映射有关吗? I've got:我有:

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

I have AJDT 1.7.3 (org.aspectj) and 2.2.3 (org.eclipse.ajdt) installed (I'm not sure why it installed both versions).我安装了 AJDT 1.7.3 (org.aspectj) 和 2.2.3 (org.eclipse.ajdt)(我不确定为什么它安装了这两个版本)。


Update 2更新 2

I updated my Aspectj-maven-plugin configuration to be the following and overrode the m2e connector settings and it seems to work, but I would love to have 3rd party validation if this works for someone else since it seems that it is editor/configuration dependant.我将我的 Aspectj-maven-plugin 配置更新为以下内容并覆盖了 m2e 连接器设置,它似乎可以工作,但如果这对其他人有效,我很乐意进行 3rd 方验证,因为它似乎依赖于编辑器/配置.

        <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>

With the following m2e configuration to override the m2e connector settings that is shipped with the AJDT/m2e 0.14 framework: org.eclipse.m2e lifecycle-mapping 1.0.0 org.codehaus.mojo aspectj-maven-plugin [1.7,) compile org.codehaus.mojo aspectj-maven-plugin [1.7,) test-compile使用以下 m2e 配置覆盖 AJDT/m2e 0.14 框架附带的 m2e 连接器设置: org.eclipse.m2e 生命周期映射 1.0.0 org.codehaus.mojo aspectj-maven-plugin [1.7,) compile org. codehaus.mojo aspectj-maven-plugin [1.7,) 测试编译

If this does work for others, the next step is to try and understand how/why the m2e connector fails, and where it needs to be fixed.如果这对其他人有效,下一步是尝试了解 m2e 连接器如何/为什么失败,以及需要修复的地方。

I uploaded my test code (including @kriegaex test project) to my github sample project: github.com/benze/aspectj-maven-plugin-defect-example.git .我将我的测试代码(包括@kriegaex 测试项目)上传到我的 github 示例项目: github.com/benze/aspectj-maven-plugin-defect-example.git 。 As per the readme, to enable/disable overriding the m2e-connector, enable the override-m2e-lifecycle profile.根据自述文件,要启用/禁用覆盖 m2e-connector,请启用 override-m2e-lifecycle 配置文件。

I have just tried to answer your question on the AspectJ users mailing list and just found the same question here.我刚刚尝试在AspectJ 用户邮件列表上回答您的问题,并在这里找到了相同的问题。 As for this part, ...至于这部分,...

I have AJDT 1.7.3 (org.aspectj) and 2.2.3 (org.eclipse.ajdt) installed (I'm not sure why it installed both versions).我安装了 AJDT 1.7.3 (org.aspectj) 和 2.2.3 (org.eclipse.ajdt)(我不确定为什么它安装了这两个版本)。

The former seems to apply to the actual AspectJ (compiler and runtime) version, in my Eclipse Luna it is 1.8.5.前者似乎适用于实际的 AspectJ(编译器和运行时)版本,在我的 Eclipse Luna 中它是 1.8.5。 The latter applies to the AJDT plugin components as such, in my IDE it is 2.2.4.后者同样适用于 AJDT 插件组件,在我的 IDE 中它是 2.2.4。


Update:更新:

Your assumption (see also your new mailing list post ) concerning M2Eclipse's lifecycle mapping - something I have never heard of before, but just looked into for the first time - being the root cause of the problem seems to be true. 您关于 M2Eclipse 生命周期映射的假设(另请参阅您的 新邮件列表帖子)——这是我以前从未听说过的,但只是第一次研究——是问题的根本原因似乎是正确的。

Sorry, this does not really work, see update 2 further below.抱歉,这实际上不起作用,请参阅下面的更新 2。

Having read this and having looked into the default lifecycle mapping in my installed m2e plugin阅读本文并查看我安装的 m2e 插件中的默认生命周期映射

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

I realised that there is not default mapping for AspectJ Maven plugin.我意识到 AspectJ Maven 插件没有默认映射。 So I just created one via menu option所以我只是通过菜单选项创建了一个

Window -> Preferences
    Maven -> Lifecycle Mappings

Eclipse m2e 生命周期映射菜单

with the following content:具有以下内容:

<?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>

This fixed your problem (which I could reproduce in my own little demo project) in my Eclipse installation.这在我的 Eclipse 安装中解决了您的问题(我可以在我自己的小演示项目中重现)。

I think it makes sense to provide a default mapping for the AspectJ Maven plugin from within M2Eclipse (someone should open a ticket, I guess) or even directly in the AspectJ Maven plugin by providing a default mapping wight in the plugin (which is said to be possible according to the M2E documentation).我认为从 M2Eclipse 中为 AspectJ Maven 插件提供默认映射是有意义的(有人应该打开一张票,我猜)或者甚至直接在 AspectJ Maven 插件中通过在插件中提供默认映射 wight(据说根据 M2E 文档是可能的)。

Here is my sample project:这是我的示例项目:

Maven project POM: 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>

Driver application:驱动程序应用:

package de.scrum_master.app;

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

Unit test:单元测试:

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");
    }
}

Test aspect (located in src/test/java ):测试方面(位于src/test/java ):

package de.scrum_master.app;

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

Console output for mvn clean package exec:java : 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] ------------------------------------------------------------------------

(...)

So it works in Maven, just like before.所以它在 Maven 中工作,就像以前一样。 But what about running the code from Eclipse via a normal run configuration?但是如何通过正常的运行配置从 Eclipse 运行代码呢?

Hello world!

No aspects there, cool!没有方面,很酷! And what about the unit tests in Eclipse?那么 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, the aspect is woven into Application.main . Tadaa,aspect 被编织到Application.main Everything works as we want it to from both Eclipse and Maven.从 Eclipse 和 Maven 中,一切都按我们希望的那样工作。


Update 2:更新 2:

I am so sorry, it only worked because I had not done a full Eclipse rebuild after the Maven build.很抱歉,它之所以有效,是因为我在 Maven 构建后没有进行完整的 Eclipse 重建。 So obviously the lifecycle mapping is not enough or maybe not even the right path to the solution.所以显然生命周期映射是不够的,甚至可能不是解决方案的正确路径。 I suppose, Eclipse is just unaware of the <weaveDirectories> setting in AspectJ Maven plugin and this is a non-trivial thing to fix.我想,Eclipse 只是不知道 AspectJ Maven 插件中的<weaveDirectories>设置,这是一个非常重要的问题。

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

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