簡體   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