繁体   English   中英

在 ForkJoinPool 方法上应用方面(非弹簧托管 bean)

[英]Apply aspect on ForkJoinPool method (non-spring managed bean)

我想将 MDC 上下文 map 复制并设置到由 spring 应用程序中的 ForkJoinPool 管理的线程。 不幸的是,我无法在执行方法上添加 aop,因为 ForkJoinPool 是非托管 spring bean。 我也不能在 ForkJoinTask 上应用 aop。 您知道如何在非 bean class 上应用 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;
    }
}

用户R.G已经为您提供了正确的线索,您只能使用本机 AspectJ 建议不是 Spring bean 的类。

在这种情况下,由于您希望在引导 class 路径上编织到 JRE class 中,因此您的任务变得更加复杂,这对于 AspectJ 来说是不容易实现的。 因此,除非您想做一些相当丑陋的事情,例如二进制 JRE class 编织并将编织的 JRE 类放在引导 class 路径上,否则我建议您只使用call()而不是execution()编织到应用程序目标类中。 这意味着您不会编织被调用者 class 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM