使 aspectj 与 scala 模型一起工作

Make aspectj work with scala model

我有一个用 Scala 创建的域和一些 class 用 Java 创建的域。我需要用 Aspectj 做一些我知道可以工作的方面,因为使用 Java class 并且它可以工作。 问题是当 Scala class 被注释时它不起作用。 hibernate 等其他注释与我的 Scala class.

配合得很好

这是我的 pom.xml:

<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/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>Group</groupId>
    <artifactId>Parent</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.source-target.version>1.8</java.source-target.version>
        <aspectj.version>1.8.2</aspectj.version>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.6.1</version>
                    <configuration>
                        <source>${java.source-target.version}</source>
                        <target>${java.source-target.version}</target>
                        <useIncrementalCompilation>false</useIncrementalCompilation>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-antrun-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>createClassesDir</id>
                            <phase>process-resources</phase>
                            <configuration>
                                <tasks>
                                    <mkdir dir="${project.build.directory}\unwoven-classes" />
                                    <mkdir dir="${project.build.directory}\classes" />
                                </tasks>
                            </configuration>
                            <goals>
                                <goal>run</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>aspectj-maven-plugin</artifactId>
                    <version>1.7</version>
                    <configuration>
                        <complianceLevel>1.8</complianceLevel>
                        <source>${aspectj.version>}</source>
                        <target>${aspectj.version>}</target>
                        <weaveDirectories>
                            <weaveDirectory>${project.build.directory}\unwoven-classes</weaveDirectory>
                        </weaveDirectories>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>process-classes</phase>
                            <goals>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>net.alchim31.maven</groupId>
                    <artifactId>scala-maven-plugin</artifactId>
                    <executions>
                        <execution>
                            <id>scala-compile-first</id>
                            <phase>process-resources</phase>
                            <goals>
                                <goal>add-source</goal>
                                <goal>compile</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>scala-test-compile</id>
                            <phase>process-test-resources</phase>
                            <goals>
                                <goal>testCompile</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${aspectj.version}</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.scala-lang</groupId>
                <artifactId>scala-library</artifactId>
                <version>2.12.1</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <modules>
        <module>Aspects</module>
    </modules>
</project>

我想我必须用 maven 做点什么,因为方面和代码的其余部分工作正常。 有办法吗?

谢谢!

问题可能是方面经常应用于您的 java 代码的语义 - "find a method with a name like X and do the following around it." 但是从 Java 来看,Scala 代码通常不遵循预期的命名惯例。如果没有关于正在制作的特定切入点以及应用它们的代码的更多详细信息,我无法提供更多见解。

首先,确保您的方面(基于注释或本机语法)始终具有 .aj 文件扩展名(通过 "New aspect" 而不是 "New class" 将它们添加到您的项目中菜单在你使用的任何 IDE 中)。我已经从我的 fork 中的你的回购中删除了重复的 class 并相应地重命名了另一个。顺便说一下,我选择了原生语法。

但更糟糕的是,您以某种方式期望未编织的 Scala classes 在特定目录中,但您没有配置 Scala 插件以实际将它们放在那里。我通过添加此代码段修复了该问题:

<configuration>
    <outputDir>${project.build.directory}/unwoven-classes</outputDir>
</configuration>

现在 AspectJ Maven 插件在那里找到 Scala classes 并对它们执行二进制编织。这修复了您的 Java 和 Scala 测试。它们之前在 Maven 中都失败了,现在至少 Java 一个在 IntelliJ 中有效,但在 Scala 中无效。这是因为 IDEA 不知道这个奇怪的 Maven 设置和你的附加(中间)目录。

因此方面本身或 AspectJ 无法使用 Scala 二进制文件并没有错。项目设置是错误的,在某种程度上它仍然是关于 IDE 支持。

那么如何彻底修复它呢?您有多种选择:

  • 将方面代码放入另一个 Maven 模块,并在那里配置对 Java + Scala 模块的编织依赖,将所有 classes 从那里编织到方面模块中。但是你可能仍然对 运行 测试有问题。但至少您可以为 post 配置 IDEA 项目-使用正确的依赖项编译编织。
  • 您也可以将 Scala 代码放在它自己的模块中,将其定义为 Java + AspectJ 模块的依赖项,然后以这种方式对其应用二进制编织。

其他变体也是可能的。我不想在这里过度分析,我只是用一种快速简单的方法修复了您的 Maven 设置,让您继续:

$ mvn clean verify

(...)
-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Aktive Codepage: 65001.
Running aspects.AnnotationAspectTest
set(String model.JavaEntity.name)
set(String model.ScalaEntity.name)
Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.055 sec

Results :

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ aspectj-with-scala ---
[INFO] Building jar: C:\Users\Alexander\Documents\java-src\aspectj-with-scala\target\aspectj-with-scala-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
(...)

P.S.: 我还创建了一个 pull request 供您轻松地将我的更改集成到您的存储库中。

P.P.S.: 看,一个 MCVE 比你之前做的更有帮助:Post 一个单独的问题只显示一个方面然后 post这里的这个问题只有一个 Maven POM。我需要两者加上其他 classes 才能重现和解决问题。在您发布 GitHub 项目后,查找和修复非常简单。