在forkjoinpool方法上应用方面(非spring托管bean)

vtwuwzda  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(470)

我想将mdc上下文Map复制并设置到spring应用程序中由forkjoinpool管理的线程。不幸的是,我不能在execute方法上添加aop,因为forkjoinpool是非托管springbean。我也不能在forkjointask上应用aop。你知道如何在非bean类上应用aop吗?或者如何将mdc上下文Map复制到forkjoinpool?

@Slf4j
@Component
@Aspect
public class ForkJoinTaskAspect {

    @Around("execution(* java.util.concurrent.ForkJoinPool.execute(..))")
    public Object executionAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
        log.debug("ForkJoinTaskAspect:: Before invoking execute() method");
        Map<String, String> contextMap = MDC.getCopyOfContextMap();
        Object value = null;
        try {
            MDC.setContextMap(contextMap);
            value = proceedingJoinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        finally {
            MDC.clear();
        }
        log.debug("ForkJoinTaskAspect:: After invoking execute() method. Return value=" + value);
        return value;
    }
}
q5iwbnjs

q5iwbnjs1#

用户r.g已经给了您正确的线索,您只能建议使用本机aspectj的类不是springbean。
在这种情况下,您的任务会更加复杂,因为您希望在引导类路径上编织成一个jre类,这在aspectj中是不容易实现的。因此,除非您想做一些相当难看的事情,比如二进制jre类编织和将编织的jre类放在引导类路径上,否则我建议您使用 call() 而不是 execution() . 这意味着您不会编织被调用方类 ForkJoinPool 但是所有的呼叫类。下面是一个小例子:

package de.scrum_master.app;

import java.util.concurrent.ForkJoinPool;

public class Application {
  public static void main(String[] args) throws InterruptedException {
    ForkJoinPool.commonPool().execute(() -> {
      System.out.println("Task executed in ForkJoinPool");
    });
    Thread.sleep(100);
  }
}
package de.scrum_master.aspect;

import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.MDC;

@Aspect
public class ForkJoinTaskAspect {
  @Around("call(* java.util.concurrent.ForkJoinPool.execute(..))")
  public Object executionAroundAdvice(ProceedingJoinPoint proceedingJoinPoint) {
    System.out.println("Before " + proceedingJoinPoint);
    Map<String, String> contextMap = MDC.getCopyOfContextMap();
    Object value = null;
    try {
      MDC.setContextMap(contextMap);
      value = proceedingJoinPoint.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    } finally {
      MDC.clear();
    }
    System.out.println("After " + proceedingJoinPoint);
    return value;
  }
}

文件 META-INF/aop.xml 可能是:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
  <aspects>
    <aspect name="de.scrum_master.aspect.ForkJoinTaskAspect" />
  </aspects>
  <weaver options="-showWeaveInfo">
    <include within="de.scrum_master.app..*" />
  </weaver>
</aspectj>

控制台日志将是:

[AppClassLoader@18b4aac2] weaveinfo Join point 'method-call(void java.util.concurrent.ForkJoinPool.execute(java.lang.Runnable))' in Type 'de.scrum_master.app.Application' (Application.java:7) advised by around advice from 'de.scrum_master.aspect.ForkJoinTaskAspect' (ForkJoinTaskAspect.aj)
Before call(void java.util.concurrent.ForkJoinPool.execute(Runnable))
After call(void java.util.concurrent.ForkJoinPool.execute(Runnable))
Task executed in ForkJoinPool

相关问题