AspectJ — синтаксический анализ определений не выполнен — NullPointerException

Вот 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 из src/main/resources

  3. Беги Junit test

Если вы удалите aop.xml, он все еще переплетается type org.*

но, с другой стороны, aop.xml не должен его плести, потому что он имеет: <include within="com.*"/> Почему он плетет что-то кроме com.* ?

Наконец, я хочу, чтобы MyAspect вызывался при запуске Junit test на основе @Around("execution(* *(..))")

Как вы можете видеть, сейчас он не вызывается.

Я сделал свой пример на основе 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)

Я хочу исправить эту ошибку


person Kamil Witkowski    schedule 20.03.2017    source источник
comment
Как вы думаете, зачем вам нужна библиотека spring-aspects? Это не приложение Spring, а чистая Java. И почему вы хотите использовать переплетение во время загрузки? Какова ваша причина сделать это? Было бы намного проще использовать плагин AspectJ Maven для плетения во время компиляции. Извините, что задаю эти вопросы, но прежде чем ответить, я хочу понять.   -  person kriegaex    schedule 20.03.2017
comment
Еще один момент: ваша сборка Maven запускает тест JUnit без переплетения во время загрузки, так почему вы хотите запускать его с LTW из IDE? Затем вы тестируете две разные вещи в зависимости от того, откуда вы запускаете тесты, что является просто плохим дизайном тестирования. Это не имеет особого смысла.   -  person kriegaex    schedule 20.03.2017
comment
Затем вы тестируете две разные вещи в зависимости от того, откуда вы запускаете тесты, что является просто плохим дизайном тестирования. Это не имеет особого смысла. Вы правы - но это метод, который я хочу показать вам (проверьте на себе), если мой aspect вызывается или нет - не более того. Тем не менее, у моих Junit test есть только 1 purpose в целом. Как вы думаете, зачем вам нужна библиотека spring-aspects? Вы правы насчет этого MVCE - я мог бы удалить его здесь. Тем не менее error происходит. Неважно, есть эта зависимость здесь или нет.   -  person Kamil Witkowski    schedule 20.03.2017
comment
@kriegaex А почему вы хотите использовать переплетение во время загрузки? Какова ваша причина сделать это? Было бы намного проще использовать плагин AspectJ Maven для плетения во время компиляции. Если я прав, это дает мне возможность проверить, работает ли мой аспект debbuging с помощью моего junit теста - и это очень удобно для меня. Я не хочу компилировать все свое приложение, чтобы посмотреть, работает ли оно. Это более быстрый способ.   -  person Kamil Witkowski    schedule 20.03.2017
comment
Это нелогично. Независимо от того, плетете ли вы код, лечащий время компиляции или загрузки, результат один и тот же. Это абсолютно не влияет на возможность отладки. Вероятно, вы не до конца понимаете, что означает АОП и, в частности, как использовать AspectJ. Если вы хотите проверить правильность применения аспектов, напишите модульные или интеграционные тесты, проверяющие их автоматически как часть набора тестов, не делайте этого вручную. Потому что тогда у вас есть именно та проблема, которую вы описываете: вы никогда не знаете, как и применяются ли они вообще. Ваш подход к управлению сборкой/тестированием совершенно неверен, и я не буду его поддерживать.   -  person kriegaex    schedule 20.03.2017
comment
Если вам нужна моя поддержка, позвольте мне помочь вам исправить вашу сборку Maven. Если он работает из Maven, IDE (например, Eclipse или IntelliJ IDEA) автоматически подберет правильные настройки при импорте проекта Maven. Сделай это правильно, не так ли?   -  person kriegaex    schedule 20.03.2017
comment
@kriegaex Я только что скачал проект - импортировал его как maven project в Eclipse - и эта ошибка возникла при запуске файла Junit test. Я не уверен, что вы хотите, чтобы я сделал. Вероятно, вы не до конца понимаете, что означает АОП и, в частности, как использовать AspectJ. Может быть, вы правы - можете ли вы показать мне лучшее решение? Если неважно, плетете ли вы код, лечащий время компиляции или загрузки, результат один и тот же. Тогда я не против использовать тот или иной метод.   -  person Kamil Witkowski    schedule 20.03.2017


Ответы (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. Ваш класс аспекта - полный беспорядок:

    • You use nested classes for no apparent reason.
    • Вы используете @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();
  }
}

Журнал консоли:

Я вижу следующее при добавлении -javaagent:/path/to/aspectjweaver.jar в мою конфигурацию запуска JUnit в IntelliJ IDEA:

[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. Я мог легко обнаружить проблемы. :-) Если бы все так делали, я бы сэкономил здесь кучу времени.

person kriegaex    schedule 20.03.2017