execute @Before and @After aspect for Runnable.run method which invoked through lambda expression

╄→尐↘猪︶ㄣ 提交于 2021-02-10 06:29:06

问题


Description How to create a pointcut for Runnable.run method So that @Before and @After aspect can be invoked in java 8 lambda expression.

  1. Create pointcut for Runnable.run method
  2. Create @Before aspect for pointcut in step 1 . ---> Print Before runnbale
  3. Create @Aefore aspect for pointcut in step 1 . ---> Print After runnable

When below line invoked

executor.runAsync(() ->

{ System.out.println("Runnable invoked"); }
)

Output expected :

Before runnable
Runnable invoked
After runnable

Solution from @AspectJ. Pointcut for scala (and probably java) lambdas not worked in this problem.

@Around("execution(void com.test..lambda*(..)) This will work for all lambda expression ... And I want to restrict this for Runnable.run method only.


回答1:


You cannot because the executed lambda methods are static, i.e. you cannot even check something like thisJoinPoint.getTarget() instanceof Runnable because the target is null. With anonymous subclasses this would work.

I.e. before something has been done about my AspectJ Bugzilla issue, you cannot really solve this problem.


Update: I found a workaround for you. It is not nice, but at least it works until AspectJ supports lambdas better. You need to tailor it to the method calling the runnable in question, though:

Driver application:

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();
  }
}

Aspect:

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);
  }
}

Console log:

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())


来源:https://stackoverflow.com/questions/49622347/execute-before-and-after-aspect-for-runnable-run-method-which-invoked-through

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!