4

我试图模仿 Spring 的AspectJ @Async 支持,但使用消息总线。

问题是我需要知道我的消息总线(RabbitMQ MessageListener)是调用该方法还是调用该方法将立即返回的普通(所有其他)调用者。

我的注释被称为@MQAsync 而不是 Springs @Async。

package com.snaphop.mqueue;

import org.apache.log4j.Logger;
import com.snaphop.mqueue.MQAsync;

public aspect MQAsyncAspect {

    //pointcut asyncTypeMarkedMethod() : execution(@MQAsync void *(..));
    pointcut asyncTypeMarkedMethod() : call(@MQAsync void *(..));

    private static final Logger log = Logger.getLogger("MQAsync");

    Object around() : asyncTypeMarkedMethod() {     
        if (listenerIsCaller) {
            return proceed();
        }
        //Send the method parameters to the message bus.
        //this logic isn't here for brevity.
        return null;
    }
}

调用切入点将为我提供调用者上下文,但这不起作用,因为我将通过反射使用消息侦听器调用该方法。执行切入点(已注释掉)不会告诉我谁在调用该方法。

有没有办法通过某种堆栈转储分析来确定调用者类?

4

3 回答 3

10

实际上, cheeken的回答很好,但是对于 AspectJcall()切入点,您可以更轻松地获取调用类,并且不会产生丑陋的反射:

thisEnclosingJoinPointStaticPart.getSignature().getDeclaringType()

如果您认为它比另一个更好,请考虑接受这个答案,否则只需享受 AspectJ 的强大功能。;-)

于 2015-04-05T16:55:56.773 回答
8

您可以通过以下调用确定哪个类正在调用当前方法。请注意,您必须捕获ClassNotFoundException(除非您对简单地将名称检索为 a 感到满意String)。

Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());

为什么是第三个元素?因为在调用堆栈跟踪方法时堆栈是这样排序的:

  1. Thread#getStackTrace()
  2. CurrentClass.currentMethod()
  3. ParentClass.parentMethod()
于 2012-06-07T04:38:58.070 回答
0

这是一种看起来更轻松的替代方法,因为它是原生的并且被 SecurityManager 常用。要使用它,我们需要一个实用程序类,因为我们需要的方法是受保护的。

public class CallStackUtils extends SecurityManager {

  static CallStackUtils sm = new CallStackUtils();

  public Class[] getCallersClassesStack0() {
    return getClassContext();
  }

  static public Class[] getCallersClassesStack() {
    return sm.getCallersClassesStack0();
  }

}
于 2015-03-26T13:50:14.563 回答