java AspectJ围绕异步方法调用保留上下文
我是AspectJ的新手,我试图弄清楚,如何保持/跟踪多个异步方法调用的上下文。想象一下下面的代码:
@TimerStart
public void doSomething() throws InterruptedException {
Thread.sleep(1000);
MyCallable callable = new MyCallable();
Future future = executorService.submit(callable );
}
private class MyCallable implements Callable {
@Override
public Object call() throws Exception {
someOtherMethod();
return null;
}
@TimerEnd
private void someOtherMethod() throws InterruptedException {
Thread.sleep(1000);
}
}
我想测量@TimerStart和@TimerEnd之间经过的时间。我现在面临两个问题:
- 我如何将一个对象保持在两个方面之间。方面中的字段似乎都是静态的,那么并发性问题呢李>
- 如何获得两个建议,一个在@TimerStart之前执行,另一个在@TimerEnd之后执行李>
目前我有一些类似的想法:
public aspect TimerAspect {
pointcut timerStart(Object object, TimerStart timed):
execution(@TimerStart * *(..)) && this(object) && @annotation(timed);
pointcut timerStop(Object object, TimerEnd timed):
cflow(execution(@TimerEnd * *(..)) && this(object) && @annotation(timed) && !within(FlowTimerAspect));
before(Object object, TimerStart timed): timerStart(object, timed) {
System.out.println("##### Flow timer START");
}
after(Object object, TimerEnd timed): timerStop(object, timed) {
System.out.println("##### Flow timer STOP");
}
然而,我现在唯一得到的是StackOverflowException(是的,我知道——这就是我在这里问的原因)
编辑:
我偶然发现了percflow
,它似乎起到了作用,但只有当@TimerStart和@TimerEnd出现在同一个线程中时。非常感谢您的建议
public aspect TimerAspect percflow(timerStart(Object, TimerStart)) {
private long context;
pointcut timerStart(Object object, TimerStart timed):
execution(@TimerStart * *(..)) && this(object) && @annotation(timed);
pointcut timerStop(Object object, TimerEnd timed):
execution(@TimerEnd * *(..)) && this(object) && @annotation(timed);
before(Object object, TimerStart timed): timerStart(object, timed) {
context = System.currentTimeMillis();
}
after(Object object, TimerEnd timed): timerStop(object, timed) {
long passed = System.currentTimeMillis() - context;
System.out.println("passed time: " + passed);
}
}
# 1 楼答案
由于您计划在测量时切换线程,
percflow
实例化方法对您没有帮助。您必须坚持默认的单例特性,并将感兴趣的对象的计时值保留在WeakHashMap
中。这样,只要与计时关联的对象/线程处于活动状态,就可以保持计时。 我们需要另一个注释来标记将新对象(本例中为Callable
)与计时关联的事件。让我们称之为@TimerJoin
。@TimerJoin
注释将类似于现有的@TimerStart
和@TimerEnd
注释。你的测量相位将如下所示以及简单的
Timer.java
类:修改callable以将其标记为加入当前线程上的计时器:
剩下的代码将是相同的
您可能会注意到,aspect使用
ThreadLocal
作为当前计时器的存储方式,以便能够将其与新对象关联。您可以为此选择另一种存储方式,但出于示例的考虑,我尽量保持简单。同样,为了简单起见,我在方面中省略了任何空值的安全检查。你需要自己处理角落里的案子