我正在尝试在独立应用程序中使用AspectJ,但似乎不起作用。
以下是我创建的课程 -
private void button1_Click(object sender, EventArgs e)
{
WebClient proxy = new WebClient();
string serviceURL =
string.Format("http://localhost:53215/IBookService.svc/GetBooksNames");
byte[] data = proxy.DownloadData(serviceURL);
var jsonString = Encoding.UTF8.GetString(data);
IList<string> bookNames = JArray.Parse(jsonString).ToObject<IList<string>>();
//Do something with the list
//foreach (string bookName in bookNames)
//{
//}
}
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);
}
}
同样在src / META_INF文件夹下我创建了aop.xml文件
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));
}
}
然后从命令行尝试使用以下命令运行Test.java时,建议中的System.out.println不会被打印 -
<aspectj>
<aspects>
<aspect name="oata.aspect.AspectJTest" />
</aspects>
<weaver>
<include within="oata.*" />
</weaver>
</aspectj>
任何人都可以让我知道我做错了什么。
由于 AA
答案 0 :(得分:1)
安迪对他所说的一切都是正确的。因为您似乎是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)。