java - AspectJ- child 类迷路了

标签 java aspectj

我确定这相当于AspectJ的“新手”问题,但是在阅读书籍和网站时,我看不到我所认识的答案。

摘要:在我的Client Jar中,我收到了编译错误,抱怨是不存在作为“方面B”的一部分添加的方法。

我有类似的设置:

         +---------------------+     
         |                     |     
         |  Client Jar         |     
         |                     |     
         +--+---------------+--+     
            |               |        
            |               |        
 +----------+----+  +-------v-------+
 | JSON Serial / |  |  Other Aspect |
 |  Deser Aspect |  +---------------+
 +-------------+-+  +-------v-------+
               |    |  Potential    |
               |    |   Other Jar   |
               |    +---------------+
               |                     
          +----v-----------+         
          |   Javabean     |         
          |   Aspects      |         
          +----------------+         
          +----v-----------+         
          |   Basic Data   |         
          |    Objects     |         
          +----------------+         


从本质上讲,我在行为的每个层面上都有两个层次。

在“基本数据对象”中假定以下类:

BasicDataObjects SampleObject


public class SampleObject {
    private String name;
    private int age;
}


以及JavaBean Aspects中的以下方面:

privileged aspect SampleObject_JavaBean {
    public String SampleObject.getName() {
       return this.name;
    }
}


以及JSON方面中的以下方面:

privileged aspect SampleObject_Json {
    public String SampleObject.getNameValue() {
       return this.name == null ? null : this.name.serialize();
    }
}


最后,在实际的客户端jar中,我得到以下作为编译错误的信息:

public void someMethod (SampleObject obj) {
    obj.getNameValue() // <-- This has a compilation error that the getNameValue() is unresolvable.
}


在我的Client Jar中,我收到了编译错误,即作为“方面B”的一部分添加的方法不可用。

我的期望是,生成“ Aspect A”的jar文件应该编译所有其自己的类以及作为“ Aspect B”的一部分提供的所有类。

方面B pom:

<project>
    <!-- (...) -->

    <artifactId>aspect-b</artifactId>

        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjrt</artifactId>
                <version>${aspectj.version}</version>
            </dependency>
            <dependency>
                <groupId>com.example</groupId>
                <artifactId>lib-data-objects</artifactId>
                <version>0.0.1-SNAPSHOT</version>
            </dependency>
        </dependencies>

        <build>
            <plugins>


        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <outxml>true</outxml>
                <complianceLevel>${java.version}</complianceLevel>
                <source>${java.version}</source>
                <target>${java.version}</target>

                <weaveDependencies>
                    <weaveDependency>
                        <groupId>com.example</groupId>
                        <artifactId>lib-data-objects</artifactId>
                    </weaveDependency>
                </weaveDependencies>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.5.1</version>
            <configuration>
                <source>${maven.compiler.source}</source>
                <target>${maven.compiler.target}</target>
            </configuration>
        </plugin>
    </plugins>
</build>

    <!-- (...) -->
</project>


方面A pom:

<project>

<!-- (...) -->

<artifactId>aspect-a</artifactId>

<dependencies>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>${aspectj.version}</version>
    </dependency>

    <dependency>
        <groupId>com.example</groupId>
        <artifactId>lib-data-objects</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>aspect-b</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <outxml>true</outxml>
                <complianceLevel>${java.version}</complianceLevel>
                <source>${java.version}</source>
                <target>${java.version}</target>

                <weaveDependencies>
                    <weaveDependency>
                        <groupId>com.example</groupId>
                        <artifactId>aspect-b</artifactId>
                    </weaveDependency>
                </weaveDependencies>
            </configuration>
        </plugin>
    </plugins>
</build>

<!-- (...) -->

</project>


客户端Jar pom:

<project>

<!-- (...) -->

<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>aspect-a-wrapper</artifactId>
        <version>${aspect-a.version}</version>
    </dependency>
    <groupId>com.example</groupId>
        <artifactId>lib-data-objects</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <version>1.7</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>test-compile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <outxml>true</outxml>
                <complianceLevel>${java.version}</complianceLevel>
                <source>${java.version}</source>
                <target>${java.version}</target>

                <weaveDependencies>
                    <weaveDependency>
                        <groupId>com.example</groupId>
                        <artifactId>aspect-a</artifactId>
                    </weaveDependency>
                </weaveDependencies>
            </configuration>
        </plugin>
    </plugins>
</build>

<!-- (...) -->

</project>

最佳答案

正如您在自己的答案中所说的那样,在客户端JAR pom.xml中,您已经定义了对两个


普通数据对象库(无方面代码)和
经过两个阶段的编织(Java Bean和JSON互类型声明),增强了方面的数据对象库。


但是您只需要后者,因此您应该删除前者。

在方面库中使用weaveDependencies是可以的,而且是必要的,因为否则它们将无法在您的情况下进行编译:方面B需要数据对象库,因为否则它将找不到应添加新方法的类。方面B需要方面A,因为它想使用已经增强了方面的库来通过ITD添加更多方法。我认为这不是一个特别好的设置,因为Aspect B需要了解Aspect A,这会创建不必要的传递依赖ClientJar -> AspB -> AspA -> DataObj。直接方面增强数据对象库并将链缩短到ClientJar -> DataObj也许更明智。仅当您确实需要在其他情况下不添加任何ITD方法的普通库时,这才是不好的。然后,您仍然可以创建一个普通的和完全增强了方面的版本(只有一个方面的方面增强,而不是两个过渡相关的阶段)。



2015年1月2日更新:

我有一些剩余时间,已经开始再次调查。我最终得到的是一个具有以下特征的不错的解决方案(请参见GitHub repo):


有一个父模块aspectj-multi-module,子模块是:


数据对象(应用程序类,无方面),无依赖项
Aspect-javabean(与Java Bean相关的ITD方面),取决于数据对象
Aspect-json(与JSON相关的ITD方面),取决于数据对象
data-objects-aspectj(将方面编织到核心类中),取决于数据对象,aspect-javabean,aspect-json
client-jar(创建包含内核+方面代码的JAR的JAR,使用使用方面增强的核心类和AspectJ运行时的主要方法创建示例类),取决于data-objects-aspectj

请注意,两个aspect- {javabean,json}模块仅依赖于核心模块,而没有aspect模块依赖于另一个模块。两种方面类型都通过二进制编织编织到模块data-objects-aspectj中的核心代码中。
为了编译ITD方面,使用了一个小技巧,但是从生成的方面库中排除了编织核心模块,因为我们只需要库中的方面。为了理解技巧,您需要了解Ajc(AspectJ编译器)的inpath和aspectpath之间的区别:


无论inpath上的内容是什么,也将在输出目录/ JAR中。相应的AspectJ Maven配置设置为<weaveDependency><weaveDependencies>部分。
Aspectpath上的所有内容仅在编译时可用,并且不会在输出目录/ JAR中结束。相应的AspectJ Maven配置设置为<aspectLibrary><aspectLibraries>部分。

因此,使用上述语义,核心模块被定义为<aspectLibrary>(即使它不包含任何方面,也不要被命名混淆)。这有效地避免了任何编织核心类成为方面库的一部分。在方面库中具有相互排斥的方面的编织核心类的多个版本将无济于事,因为最后哪个应该赢?我们需要一个同时包含所有方面库的核心代码版本,或者至少我们选择在另一个模块中进行配置的所有方面库。
刚刚提到的另一个模块是data-objects-aspectj,其唯一目的是使用纯Java核心模块和两个纯方面库作为输入进行后编译,二进制方面编织。这次将所有这些模块都配置为<weaveDependencies>,因为所有模块都应位于结果JAR中。为了在AspectJ Maven插件中启用二进制编织,我们需要添加一个虚拟类,因为如果该插件在其自己的模块中找不到任何源文件,则该插件不会编译或编织任何东西。通过在Maven JAR插件中配置的显式排除,再次从输出中删除虚拟类。排除很高兴,您也可以忽略输出JAR中的虚拟类。
最后但并非最不重要的一点是,有一个模块client-jar,它向整个混合添加了一个带有main方法的小驱动程序,以使其可从命令行运行和测试。驱动程序应用程序使用JSON和Java Bean方面创建的getter方法,以证明它们确实存在并且可以正常工作。
client-jar模块中的另一个优点是创建了一个包含所有依赖项(甚至包括AspectJ运行时)和主类配置的One-JAR(über-JAR)。实际上,您可以通过以下方式运行结果:java -jar client-jar/target/client-jar-1.0-SNAPSHOT.one-jar.jar
最后,模块client-jar还包含一个Exec Maven插件配置,用于通过以下命令直接运行über-JAR。就像über-JAR一样,这也很有趣,但是为什么要使生活变得比必要的更加艰难呢? ;-)


控制台输入/输出:

$ java -jar client-jar/target/client-jar-1.0-SNAPSHOT.one-jar.jar

SampleObject{name='John Doe', age=33}

Java Bean properties:
  John Doe
  33

JSON properties:
  "Name" : "John Doe"
  "Age" : 33




2015年1月3日更新:

我添加了通过Maven概要文件在模块data-objects-aspectj编织过程中创建应用于核心代码的方面的自定义混合的功能,请参见changeset 32ee5fc

关于java - AspectJ- child 类迷路了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26495125/

相关文章:

java - 使用Aspectj调用joinPoint.getArgs时如何忽略带有javax注释的参数?

java - 我为 AspectJ 使用哪个 maven 插件?

java - Aspectj:从 HttpServletRresponse 获取响应正文(HTML 文本)

java - 如何使用AspectJ(cflow)实现Wormhole模式

Java 应用程序存在大量内存问题

java - 如何在没有 By 定位器的情况下使用 WebDriverWait.until?

java - 将无状态注入(inject) ManagedBean

java - 如何使内部 Java 包在 Eclipse 中可访问?

java - 为什么 Java 不允许扩展类型参数?

java - AspectJ-使用if()表达式的切入点导致无限递归