簡體   English   中英

AspectJ方面不適用於LTW場景

[英]AspectJ aspect is not applied in LTW scenario

我正在嘗試在獨立應用程序中使用AspectJ,但似乎無法正常工作。

這是我創建的課程-

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時,從命令行中不會打印建議中的System.out.println-

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

誰能讓我知道我做錯了什么。

謝謝AA

一些事情:

  • 您的META-INF/*文件夾是否肯定會復制到運行應用程序的bin文件夾中?
  • 您正在指定oata.*的include,它將僅包含oata包中的直接類,如果您需要其他子包(我想這樣做),則需要oata..*
  • 您是否嘗試過指定weaver options="-verbose" -這會顯示任何內容嗎? 如果未顯示任何內容,則找不到aop.xml文件。 如果確實顯示了某些內容,它將告訴您哪些方面已打開。 也許然后用-debug對其進行擴充,以了解發生了什么。
  • 我可能會向您的切入點添加!within(AspectJTest)投訴,否則您最終可能會自我建議,並在堆棧開始工作時因堆棧溢出而失敗。
  • 最后,我知道您現在不使用它,但是如果您打算使用該注釋與AspectJ進行匹配,則您需要將其從SOURCE保留中更改,因為AspectJ在字節碼級別起作用,並且看不到它是否具有源保留。

安迪(Andy)的一切都對。 因為您似乎是AspectJ和Java的新手,所以我對示例代碼進行了一些重構,以幫助您入門。 我一路上注意到的事情:

  • 您使用了非常舊的AspectJ版本1.6.10。 它來自2010年,甚至不是最新的1.6版本(即1.6.12)。 如何使用當前的AspectJ 1.8.6版?
  • 我是一個干凈的代碼專家,並且注意到您的類名使您想在示例代碼中演示的內容變得晦澀難懂。 所以我重命名了它們:
    • TestApplication
    • TestAspectHelper
    • AspectTestMyAnnotation
    • AspectJTestMethodInterceptor
  • 我還更改了Helper方法的返回類型,以返回除void以外的其他內容,以演示下一個問題。
  • 您的@Around建議的返回類型為void 這樣,如果切入點碰到了非空方法,它將無法正常工作。 我將返回類型更改為Object ,並將代碼更改為返回proceed()的結果,以展示如何以更通用的方式完成此操作。
  • 您的@Around建議始終記錄相同的消息。 我更新它來記錄實際的連接點信息(之前和之后proceed()調用),所以我們可以看到什么是在控制台日志發生。
  • 如Andy所說,很明顯,您計划使用批注以將帶有批注的方法與切入點匹配。 因此,我將保留范圍更改為RUNTIME
  • 切入點針對所有方法執行,包括Application.mainHelper.doItWithout 我將切入點更改為僅使用@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)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM