【问题标题】:Why is aspectj weaving Aspects from my test folder into my source classes (as opposed to the test classes)?为什么 aspectj 将我的测试文件夹中的 Aspects 编织到我的源类中(而不是测试类)?
【发布时间】:2015-06-16 20:20:57
【问题描述】:

我在使用 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 构建路径配置,我会看到 src/main/java -> target/classes 而 src/test/java-> target/test-classes。

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

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 连接器设置,它似乎可以工作,但如果这对其他人有效,我希望进行第 3 方验证,因为它似乎是编辑器/配置依赖。

        <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 配置文件。

【问题讨论】:

    标签: java eclipse maven aspectj aspectj-maven-plugin


    【解决方案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
    

    内容如下:

    <?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 插件中通过在插件中提供默认映射 wight(其中根据 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 插件中的 &lt;weaveDirectories&gt; 设置,这是一个非常重要的修复。

    【讨论】:

    • 我在周五尝试了类似的方法,似乎可以正常工作。请同时查看我的更新 2。它与您的配置类似,但我采用了更详细的方法来定义编织配置。您能否在您的测试项目和环境中快速对其进行测试,并让我知道它是否有效?我在我的两个项目中尝试过它,它似乎可以正常工作。
    • 我尝试了您的代码,并且不得不修改 pom 中的一些内容,但它似乎也可以在我的系统上运行,并使用我更新的 aspectj 配置。最重要的事情似乎是确保正确应用 m2e 生命周期映射:右键单击 project->Maven->Lifecycle mappings 以确认它没有设置为“配置器 - 源插件”,而是“执行 - pom "。
    • 我将我的新代码(包括你的测试项目)上传到我的 github 示例项目:github.com/benze/aspectj-maven-plugin-defect-example.git。根据自述文件,要启用/禁用覆盖 m2e-connector,请启用 override-m2e-lifecycle 配置文件。
    • 对不起,不,结果与您更复杂的配置相同,我自己的配置。在 Eclipse 重新构建后,仅在 Maven 构建之后,使用普通 Eclipse 运行配置将 de.scrum_master.app.Application 运行为 Java 不起作用。我仍然收到java.lang.NoClassDefFoundError: de/scrum_master/app/TestAspect
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    • 2022-12-22
    • 2019-05-15
    • 2015-03-31
    相关资源
    最近更新 更多