描述 如何为Runnable.run方法创建切入点以便可以在java 8 lambda表达式中调用@Before和@After方面。
调用以下行时
executor.runAsync(() ->
{ System.out.println("Runnable invoked"); }
)
预期输出:
Before runnable
Runnable invoked
After runnable
来自@AspectJ. Pointcut for scala (and probably java) lambdas的解决方案无法解决此问题。
@Around(" execution(void com.test..lambda *(..)) 这适用于所有lambda表达式......我想仅限于Runnable.run方法。
答案 0 :(得分:1)
你不能因为执行的lambda方法是静态的,即你甚至无法检查像thisJoinPoint.getTarget() instanceof Runnable
这样的东西,因为目标是null。使用匿名子类,这将有效。
即。在关于AspectJ Bugzilla issue的事情已经完成之前,你无法真正解决这个问题。
更新:我找到了一个解决方法。这不好,但至少它可以工作,直到AspectJ更好地支持lambdas。你需要将它定制为调用有问题的runnable的方法,但是:
驱动程序应用程序:
package de.scrum_master.app;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
public class Application {
public static void main(String[] args) throws InterruptedException, ExecutionException {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
System.out.println("Separate thread lambda");
});
CompletableFuture<Void> future2 = CompletableFuture.runAsync(new Runnable() {
@Override
public void run() {
try {
MILLISECONDS.sleep(100);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
System.out.println("Separate thread anonymous Runnable");
}
});
System.out.println("Main thread");
future.get();
future2.get();
}
}
<强>方面:强>
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class AsyncRunInterceptor {
private static final String CLASS_ASYNC_RUN = "java.util.concurrent.CompletableFuture$AsyncRun";
private static final String METHOD_RUN = "run";
@Pointcut("execution(void *(..)) && !within(de.scrum_master.aspect.AsyncRunInterceptor) && if()")
public static boolean isAsyncRun() {
final StackTraceElement[] stackTrace = new Exception().getStackTrace();
if (stackTrace.length < 3)
return false;
final StackTraceElement stackTraceElement = stackTrace[2];
return
stackTraceElement.getClassName() == CLASS_ASYNC_RUN
&& stackTraceElement.getMethodName() == METHOD_RUN;
}
@Before("isAsyncRun()")
public void beforeAsyncRun(JoinPoint thisJoinPoint) {
System.out.println("[" + Thread.currentThread().getId() + "] BEFORE " + thisJoinPoint);
}
@After("isAsyncRun()")
public void afterAsyncRun(JoinPoint thisJoinPoint) {
System.out.println("[" + Thread.currentThread().getId() + "] AFTER " + thisJoinPoint);
}
}
控制台日志:
Main thread
[10] BEFORE execution(void de.scrum_master.app.Application.lambda$0())
[11] BEFORE execution(void de.scrum_master.app.Application.1.run())
Separate thread lambda
Separate thread anonymous Runnable
[11] AFTER execution(void de.scrum_master.app.Application.1.run())
[10] AFTER execution(void de.scrum_master.app.Application.lambda$0())