2015-08-22 5 views
0

Я пытаюсь использовать AspectJ в автономном приложении, но, похоже, не работает.Аспект AspectJ не применяется в сценарии LTW

Вот классы I created-

package oata.aspect; 

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

@Aspect 
public class AspectJTest { 


    @Around("execution(* *..*(..))") 
    public void around(ProceedingJoinPoint jp) throws Throwable { 
     System.out.println("around fired"); 
     jp.proceed(); 
    } 
} 
package oata; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Target(value = ElementType.METHOD) 
@Retention(RetentionPolicy.SOURCE) 
public @interface AspectTest { 
} 
package oata; 

import oata.AspectTest; 

public class TestAspect { 
    public void doItWithout(int i) { 
     double s = Math.acos(i); 
    } 

    @AspectTest 
    public void doItAnnotated(int i) { 
     double s = Math.acos(i); 
    } 

    public void doItAspect(int i) { 
     double s = Math.acos(i); 

    } 
} 
package oata; 

import java.util.Date; 

public class Test { 
    public Test() { 
    } 

    public static void main(String arg[]) { 
     // performance testing 
     // invoke method without aspect 
     long t1 = new Date().getTime(); 
     for (int i = 0; i < 1; i++) { 
      new TestAspect().doItWithout(i); 
     } 
     System.out.println("Invoke without aspect:" 
       + (new Date().getTime() - t1)); 
     // invoke method with annotated aspect 
     t1 = new Date().getTime(); 
     for (int i = 0; i < 1; i++) { 
      new TestAspect().doItAnnotated(i); 
     } 
     System.out.println("Invoke annotated aspect method:" 
       + (new Date().getTime() - t1)); 
     // invoke method with aspect but not annotated 
     t1 = new Date().getTime(); 
     for (int i = 0; i < 1; i++) { 
      new TestAspect().doItAspect(i); 
     } 
     System.out.println("Invoke aspect method:" 
       + (new Date().getTime() - t1)); 
    } 
} 

Также под Src/папку META_INF Я создал файл aop.xml

<aspectj> 
    <aspects> 
     <aspect name="oata.aspect.AspectJTest" /> 
    </aspects> 
    <weaver> 
     <include within="oata.*" /> 
    </weaver> 
</aspectj> 

Тогда из когда я пытаюсь запустить Test.java с помощью belo ж команды System.out.println в совет не получает printed-

\TestAspectJ\bin>java -javaagent:D:\Project\workspaces\RCS_3.2.1\TestAspectJ\src\aspectjweaver-1.6.10.jar oata.Test 

Может кто-нибудь пожалуйста, дайте мне знать, что это такое, что я делаю неправильно.

Благодаря AA

+0

Я изменил тему, чтобы отразить то, что вы просите. В частности, я удалил часть «в приложении non-Spring», потому что AspectJ абсолютно не зависит от Spring, так что не стоит упоминать об этом. Использование его в дополнение к или вместо Spring AOP из Spring - скорее специальность, а не обычный случай. – kriegaex

ответ

2

Немногие вещи:

  • Ваша META-INF/* папка определенно копируется в папку бин, где вы запускаете приложение из?
  • Вы определяете включаемый из oata.*, который будет включать в себя только прямые классы в пакете oata, если вы хотите, дополнительные пакеты к югу (и я думаю, что вы делаете), вам необходимо oata..*
  • Вы пробовали указания weaver options="-verbose" - делает это шоу вы что-нибудь? Если он ничего не показывает, файл aop.xml не будет найден. Если он покажет вам что-то, он скажет вам, какие аспекты включены. Возможно, затем увеличьте его с помощью -debug, чтобы узнать больше о том, что происходит.
  • Я мог бы включить жалобу !within(AspectJTest) в ваш pointcut или вы могли бы самостоятельно самообслуживать и терпеть неудачу при переполнении стека, когда он начнет работать.
  • Наконец, я знаю, что вы не используете его сейчас, но если вы собираетесь использовать эту аннотацию для соответствия с AspectJ, вам нужно будет изменить ее с SOURCE, поскольку AspectJ работает на уровне байтового кода и не увидит, имеет удержание источника.
1

Энди прав со всем, что он сказал. Поскольку вы, похоже, новичок в AspectJ, а также Java, я немного переработал ваш пример кода, чтобы помочь вам начать работу. Вещи, которые я заметил на этом пути:

  • Вы используете очень старую версию AspectJ 1.6.10. Это с 2010 года и даже не последняя версия 1.6 (которая будет 1,6.12). Как насчет использования текущей версии AspectJ 1.8.6?
  • Я чистый парень кода и заметил, что ваши имена классов довольно запутывают то, что вы хотите продемонстрировать с помощью образца кода.Так что я переименовал их:
    • TestApplication
    • TestAspectHelper
    • AspectTestMyAnnotation
    • AspectJTestMethodInterceptor
  • Я также изменил типы Возвратите Helper методы, чтобы вернуть что-то кроме void для демон укажите следующий вопрос.
  • Ваш @Around совет имеет тип возврата void. Таким образом, он не работает, если pointcut попадает в непустой метод. Я изменил тип возврата на Object и код, чтобы вернуть результат proceed(), чтобы показать, как это можно сделать более общим образом.
  • Ваш совет @Around всегда регистрирует одно и то же сообщение. Я обновил его, чтобы зарегистрировать фактическую информацию о соединении (до и после вызова proceed()), чтобы мы могли видеть, что происходит в журнале консоли.
  • Как сказал Энди, очевидно, что вы планируете использовать аннотацию, чтобы соответствовать аннотированным методам с помощью pointcut. Таким образом, я изменил область хранения на RUNTIME.
  • Ваша pointcut предназначена для всех методов, включая Application.main и . Я изменил pointcut только на целевые методы, либо несущие @MyAnnotation, либо подстроку «Aspect» в имени своего метода.
  • Кажется, что вы хотите просмотреть время выполнения метода и сравнить методы с аспектами, применяемыми к методам, не ориентированным на аспекты. Вместо создания большого количества экземпляров Date и вызова new Date().getTime() (возвращает миллисекунды) вы можете просто использовать System.nanoTime() (возвращает наносекунды).
  • При профилировании вы хотите измерить время выполнения метода, а не время создания объекта. Таким образом, я изменил код, чтобы просто создать один экземпляр Helper, который затем повторно используется во всем методе main.
  • Класс Application не нуждается в пустом конструкторе по умолчанию, поскольку он автоматически генерируется JVM.
  • Чтобы получить значимые результаты профилирования, вы должны использовать большее количество повторений (например, миллион). Я представил константу с именем LOOP_COUNT, чтобы упростить это для всех трех циклов.
  • Внимание! Если вы хотите измерить время выполнения метода, вы не должны печатать что-либо в своем аспекте, потому что тогда вы также будете измерять время, необходимое для записи чего-либо на консоль. Таким образом, я прокомментировал заявления печати в этом аспекте. Вы можете активировать их для меньшего количества повторений, чтобы увидеть, что происходит.

рефакторинга код:

package oata; 

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

@Target(value = ElementType.METHOD) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation {} 
package oata; 

import oata.MyAnnotation; 

public class Helper { 
    public double doItWithout(int i) { 
     return Math.acos(i); 
    } 

    @MyAnnotation 
    public double doItAnnotated(int i) { 
     return Math.acos(i); 
    } 

    public double doItAspect(int i) { 
     return Math.acos(i); 
    } 
} 
package oata; 

public class Application { 
    private static final int LOOP_COUNT = 100000000; 

    public static void main(String arg[]) { 
     Helper helper = new Helper(); 
     System.out.printf(
      "Profiling statistics for %,d repetitions%n%n", 
      LOOP_COUNT 
     ); 

     long startTime = System.nanoTime(); 
     for (int i = 0; i < LOOP_COUNT; i++) 
      helper.doItWithout(i); 
     System.out.printf(
      "Method not targeted by aspect:%n %,15d ns%n", 
      System.nanoTime() - startTime 
     ); 

     startTime = System.nanoTime(); 
     for (int i = 0; i < LOOP_COUNT; i++) 
      helper.doItAnnotated(i); 
     System.out.printf(
      "Method targeted by aspect because it is annotated:%n %,15d ns%n", 
      System.nanoTime() - startTime 
     ); 

     startTime = System.nanoTime(); 
     for (int i = 0; i < LOOP_COUNT; i++) 
      helper.doItAspect(i); 
     System.out.printf(
      "Method targeted by aspect because of its name:%n %,15d ns%n", 
      System.nanoTime() - startTime 
     ); 
    } 
} 
package oata.aspect; 

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

@Aspect 
public class MethodInterceptor { 
    @Around("execution(@oata.MyAnnotation * *(..)) || execution(* *Aspect*(..))") 
    public Object around(ProceedingJoinPoint jp) throws Throwable { 
//  System.out.println("BEFORE " + jp); 
     Object result = jp.proceed(); 
//  System.out.println("AFTER " + jp); 
     return result; 
    } 
} 

Образец журнала консоли для 1 повторения с операторами аспект журнала включено:

Profiling statistics for 1 repetitions 

Method not targeted by aspect: 
      153.893 ns 
BEFORE execution(double oata.Helper.doItAnnotated(int)) 
AFTER execution(double oata.Helper.doItAnnotated(int)) 
Method targeted by aspect because it is annotated: 
      3.102.128 ns 
BEFORE execution(double oata.Helper.doItAspect(int)) 
AFTER execution(double oata.Helper.doItAspect(int)) 
Method targeted by aspect because of its name: 
      55.295 ns 

Как вы можете видеть здесь, результаты не очень убедительны только с одним вызовом на метод.

Образец журнала консоли для 100.000.000 (сто миллионов) повторы с утверждениями аспект журнала отключенными:

Profiling statistics for 100.000.000 repetitions 

Method not targeted by aspect: 
     843.407.034 ns 
Method targeted by aspect because it is annotated: 
     1.219.571.173 ns 
Method targeted by aspect because of its name: 
     1.175.436.574 ns 

Теперь результат более убедительным: метод не нацелен на какой-либо аспект выполняется быстрее, чем следующие два метода, которые имеют примерно равное время выполнения 1,2 секунды, что следовало ожидать, потому что используемые точки могут быть определены статически во время компиляции (для CTW) или времени ткачества (для LTW).

Смежные вопросы