【问题标题】:Make aspectj work with scala model使 aspectj 与 scala 模型一起工作
【发布时间】:2017-04-13 22:29:37
【问题描述】:

我有一个用 Scala 制作的域和一些用 Java 制作的类。我需要用我知道的 Aspectj 做一些工作,因为使用 Java 类并且它可以工作。 问题是当 Scala 类被注释时它不起作用。 hibernate 等其他注释与我的 Scala 类配合得很好。

这是我的 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 scala aop aspectj aspectj-maven-plugin


    【解决方案1】:

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

    然而,更糟糕的是,您以某种方式期望未编织的 Scala 类位于特定目录中,但您没有配置 Scala 插件以实际将它们放在那里。我通过添加这个 sn-p 解决了这个问题:

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

    现在 AspectJ Maven 插件在那里找到了 Scala 类并对其执行二进制编织。这修复了您的 Java 和 Scala 测试。他们之前在 Maven 中都失败了,现在至少 Java 可以在 IntelliJ 中工作,但不能在 Scala 中工作。这是因为 IDEA 不知道这个奇怪的 Maven 设置以及您的附加(中间)目录。

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

    那么如何才能彻底解决它呢?您有多种选择:

    • 将切面代码放入另一个 Maven 模块,并在那里配置对 Java + Scala 模块的编织依赖项,将所有类从那里编织到切面模块中。但是,您可能仍然在运行测试时遇到问题。但至少您可以配置 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 比您以前所做的更有帮助:发布一个单独的问题,仅显示一个方面,然后在此处仅使用 Maven POM 发布此问题。为了重现和解决问题,我需要这两个类以及其他类。发布 GitHub 项目后,查找和修复非常简单。

    【讨论】:

    • 非常感谢!该解决方案在我上传的项目上完美运行,我已经接受了拉取请求并对其进行了一些修改以使其成为多模块。感谢您的耐心和帮助!
    • 我刚刚发布了我的最后一个问题here,如果可能的话,你能帮我吗?谢谢!
    • 对于所有可能阅读此内容的其他人:@Motomine 的多模块设置已损坏,Maven 和 IntelliJ IDEA 中的测试都失败了。如果在我的fork 中修复它并发出另一个拉取请求。因此,如果有人正在寻找支持 Scala 的 AspectJ 多模块设置的展示柜,您可以在那里找到。
    【解决方案2】:

    问题很可能是方面经常应用于您的 java 代码的语义——“找到一个名称类似于 X 的方法并围绕它执行以下操作。”但是,从 Java 来看,Scala 代码通常不遵循预期的命名约定。如果没有更多关于具体切入点的详细信息 - 以及它们所应用的代码 - 我无法提供更多的见解。

    【讨论】:

    • 我同意。正如我在您的另一个问题中所说,请在 GitHub 上发布带有代码和构建配置的完整 MCVE。也许然后我可以通过分析您的设置为您找到解决方案。
    • 我明白你的意思并且我理解它,但是当我使用注释时,我认为这可能不会发生。代码很多,我一会儿把我有的上传到 GitHub 看看你能不能帮帮我。谢谢
    • @kriegaex 我刚刚上传了一个完整的例子here。在此示例中,使用 Java 类运行的测试有效,而使用 Scala 类的测试失败
    • 好吧,我最好的办法是您已将注释应用到var name。您的设置切入点需要一个名为“name”的属性和一个设置它的方法,但就像 scala 对象上的所有其他内容一样,它是作为方法而不是字段实现的(您可以通过编写 new ScalaEntity().name(); 从您的 java 代码中看到这一点) .在这种情况下,实现将是两个方法,因为 var 是可变的而被重载。如果可以信任以前的方面经验,AspectJ 甚至可能正在寻找“setName”。但是 ScalaEntity 上的方法不符合该标准。
    • 我明白你的意思,但是编写一个方法 setName 并调用它也不起作用。我认为这可能是一种方法,可能是因为 scala 类是在方面之后编译的。这是您建议的解决方案吗?
    猜你喜欢
    • 2015-07-28
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-04
    • 2011-10-25
    相关资源
    最近更新 更多