[英]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)
投訴,否則您最終可能會自我建議,並在堆棧開始工作時因堆棧溢出而失敗。 SOURCE
保留中更改,因為AspectJ在字節碼級別起作用,並且看不到它是否具有源保留。 安迪(Andy)的一切都對。 因為您似乎是AspectJ和Java的新手,所以我對示例代碼進行了一些重構,以幫助您入門。 我一路上注意到的事情:
Test
→ Application
TestAspect
→ Helper
AspectTest
→ MyAnnotation
AspectJTest
→ MethodInterceptor
Helper
方法的返回類型,以返回除void
以外的其他內容,以演示下一個問題。 @Around
建議的返回類型為void
。 這樣,如果切入點碰到了非空方法,它將無法正常工作。 我將返回類型更改為Object
,並將代碼更改為返回proceed()
的結果,以展示如何以更通用的方式完成此操作。 @Around
建議始終記錄相同的消息。 我更新它來記錄實際的連接點信息(之前和之后proceed()
調用),所以我們可以看到什么是在控制台日志發生。 RUNTIME
。 Application.main
和Helper.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.