【问题标题】:AspectJ - parse definitions failed - NullPointerExceptionAspectJ - 解析定义失败 - NullPointerException
【发布时间】:2017-03-20 14:41:31
【问题描述】:

这里是MVCE https://github.com/yami12376/AspectJ

  1. VM arguments 添加到Run/Debug configuration of Junit test,在我的例子中:

    -javaagent:C:\aspectjWeaver\spring-instrument-3.0.4.jar

    -javaagent:C:\aspectjWeaver\aspectjweaver-1.6.11.jar

  2. 就我而言,我在JAVA build path 中添加了这个:\target\classes\META-INF from src/main/resources

  3. 运行Junit test

如果你删除aop.xml,它仍然在编织type org.*

但另一方面,aop.xml 不应该编织它,因为它有: <include within="com.*"/> 为什么它会编织com.*以外的东西?

最后我希望在基于@Around("execution(* *(..))") 运行Junit test 时调用MyAspect

你现在可以看到它没有被调用。

我的示例基于 https://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw-first-example

在运行JUnit test 时,我看到了这个错误:

http://wklej.org/id/3066582/

 [AppClassLoader@18b4aac2] warning parse definitions failed -- (NullPointerException) null
null
java.lang.NullPointerException
    at org.aspectj.weaver.loadtime.definition.DocumentParser.resolveEntity(DocumentParser.java:177)
    at org.apache.xerces.util.EntityResolverWrapper.resolveEntity(Unknown Source)
    at org.apache.xerces.impl.XMLEntityManager.resolveEntity(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentScannerImpl$DTDDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
    at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
    at org.aspectj.weaver.loadtime.definition.DocumentParser.saxParsing(DocumentParser.java:158)
    at org.aspectj.weaver.loadtime.definition.DocumentParser.parse(DocumentParser.java:123)
    at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.parseDefinitions(ClassLoaderWeavingAdaptor.java:272)
    at org.aspectj.weaver.loadtime.DefaultWeavingContext.getDefinitions(DefaultWeavingContext.java:130)
    at org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor.initialize(ClassLoaderWeavingAdaptor.java:156)
    at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.initialize(Aj.java:340)
    at org.aspectj.weaver.loadtime.Aj$ExplicitlyInitializedClassLoaderWeavingAdaptor.getWeavingAdaptor(Aj.java:345)
    at org.aspectj.weaver.loadtime.Aj$WeaverContainer.getWeaver(Aj.java:319)
    at org.aspectj.weaver.loadtime.Aj.preProcess(Aj.java:113)
    at org.aspectj.weaver.loadtime.ClassPreProcessorAgentAdapter.transform(ClassPreProcessorAgentAdapter.java:54)
    at sun.instrument.TransformerManager.transform(Unknown Source)
    at sun.instrument.InstrumentationImpl.transform(Unknown Source)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(Unknown Source)
    at java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.defineClass(Unknown Source)
    at java.net.URLClassLoader.access$100(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)

我想修正这个错误

【问题讨论】:

  • 为什么你认为你需要 spring-aspects 库?它不是 Spring 应用程序,而是纯 Java。为什么要使用加载时编织?你这样做的理由是什么?使用 AspectJ Maven 插件进行编译时编织会容易得多。很抱歉提出这些问题,但在回答之前我想了解一下。
  • 还有一件事:您的 Maven 构建运行 JUnit 测试而没有加载时编织,那么为什么要使用 IDE 中的 LTW 运行它呢?然后,根据运行测试的位置,您正在测试两种不同的东西,这只是糟糕的测试设计。这没有多大意义。
  • " 那么你正在测试两个不同的东西,这取决于你从哪里运行测试,这只是糟糕的测试设计。它没有多大意义。“你是对的 - 但这是我想要的方法如果我的aspect 是否被调用,向您展示(检查自己) - 仅此而已。我的Junit test 通常只有1 purpose。 “你为什么认为你需要 spring-aspects 库?”对于这个 MVCE,你是对的——我可以在这里删除它。仍然出现error。这个依赖是否在这里并不重要。
  • @kriegaex " 为什么要使用加载时编织?您这样做的原因是什么?使用 AspectJ Maven 插件进行编译时编织会容易得多。"如果我是正确的,这让我有机会使用我的junit 测试检查我的方面是否通过debbuging 工作 - 这对我来说非常舒服。我不想编译我的整个应用程序来查看它是否有效。这是更快的方式。
  • 这是不合逻辑的。无论你编织代码固化编译还是加载时间,结果都是一样的。它对可调试性绝对没有影响。可能您不完全理解 AOP 的含义以及具体如何使用 AspectJ。如果您想检查方面是否被正确应用,编写单元或集成测试作为测试套件的一部分自动检查它,不要手动进行。因为那时您就遇到了您描述的问题:您永远不知道它们是如何/是否被应用的。你的构建/测试管理方法是完全错误的,我不会支持它。

标签: java eclipse junit aspectj aspect


【解决方案1】:

嗯,您的项目中有几个奇怪的问题和错误:

  1. 显然您的 POJO 应用程序不使用 Spring。因此,您可以摆脱 Spring 依赖项以及命令行上的 spring-instrument.jar。你也不需要core-context.xml
  2. 据我所知,也不需要 Xerces。
  3. 如果您使用 aspectjweaver.jar 作为依赖项,aspectjrt.jar 是多余的,因为前者是超集,因此包含后者。
  4. aop.xml 中有一个包名拼写错误:请在方面名称中使用com.mkyong,而不是com.mykong。否则将永远找不到方面。
  5. 在您的include within 标记中,您应该使用.. 语法以便同时包含/排除子包。
  6. 你的方面类是一团糟:

    • 您无缘无故地使用嵌套类。
    • 您使用@Around,但在建议签名中使用JoinPoint 而不是ProceedingJoinPoint
    • 你使用@Around,但从不调用proceed()

那么这个怎么样?

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>com.mkyong</groupId>
  <artifactId>NumberGenerator</artifactId>
  <version>1.0-SNAPSHOT</version>

  <name>NumberGenerator</name>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.8.10</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.0</version>
        <configuration>
          <source>1.7</source>
          <target>1.7</target>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

aop.xml:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
  <aspects>
    <aspect name="com.mkyong.MyAspect"/>
  </aspects>
  <weaver options="-verbose -showWeaveInfo">
    <include within="com.mkyong..*"/>
    <exclude within="org.jibx*..*"/>
  </weaver>
</aspectj>

方面:

package com.mkyong;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
  @Around("execution(!static * *(..))")
  public Object dontLogDuplicates(ProceedingJoinPoint thisJoinPoint) throws Throwable {
    System.out.println(thisJoinPoint);
    return thisJoinPoint.proceed();
  }
}

控制台日志:

在 IntelliJ IDEA 中将 -javaagent:/path/to/aspectjweaver.jar 添加到我的 JUnit 运行配置时,我看到以下内容:

[AppClassLoader@18b4aac2] info AspectJ Weaver Version 1.8.10 built on Monday Dec 12, 2016 at 19:07:48 GMT
[AppClassLoader@18b4aac2] info register classloader sun.misc.Launcher$AppClassLoader@18b4aac2
[AppClassLoader@18b4aac2] info using configuration /C:/Users/Alexander/Documents/java-src/yami12376-AspectJ/target/classes/META-INF/aop.xml
[AppClassLoader@18b4aac2] info register aspect com.mkyong.MyAspect
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(void com.mkyong.AppTest.testLengthOfTheUniqueKey())' in Type 'com.mkyong.AppTest' (AppTest.java:9) advised by around advice from 'com.mkyong.MyAspect' (MyAspect.java)
execution(void com.mkyong.AppTest.testLengthOfTheUniqueKey())
[AppClassLoader@18b4aac2] weaveinfo Join point 'method-execution(java.lang.String com.mkyong.App.generateUniqueKey())' in Type 'com.mkyong.App' (App.java:12) advised by around advice from 'com.mkyong.MyAspect' (MyAspect.java)
execution(String com.mkyong.App.generateUniqueKey())

但实际上,您应该修复您的 POM 并确保从那里完成切面编织而不是手动完成。这样子真的很丑。

更新:在所有的批评之后,我还要说一件积极的事情:你提供了一个 MCVE,谢谢。有了代码片段、问题和答案,我们永远不会在您的文件中发现许多错误。因此,创建 GitHub 项目是一个明智而谨慎的决定。我可以很容易地发现问题。 :-) 如果每个人都这样做,我会在这里节省很多时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-22
    • 2019-07-22
    • 2014-04-05
    • 2011-03-28
    • 2019-09-27
    • 2012-10-23
    相关资源
    最近更新 更多