我正在尝试模仿Spring的AspectJ @Async support但是使用消息总线。
问题是我需要知道我的消息总线(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;
}
}
调用切入点将获取调用者上下文,但这不起作用,因为我将通过反射调用我的消息侦听器的方法。 执行切入点(已注释掉)不会告诉我谁在调用该方法。
有没有办法通过某种堆栈转储分析来确定调用者类?
答案 0 :(得分:10)
实际上 cheeken 的答案很好,但是对于AspectJ call()
切入点,你可以更轻松地获得调用类,而不会出现难看的反射:
thisEnclosingJoinPointStaticPart.getSignature().getDeclaringType()
如果你觉得它比另一个更好,请考虑接受这个答案,否则只是享受AspectJ的力量。 ;-)
答案 1 :(得分:8)
您可以使用以下调用确定哪个类正在调用当前方法。请注意,您必须抓住ClassNotFoundException
(除非您只是将名称检索为String
,否则感到满意。)
Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
为什么第三个元素?因为在调用堆栈跟踪方法时堆栈是这样排序的:
Thread#getStackTrace()
CurrentClass.currentMethod
()
ParentClass.parentMethod
()
答案 2 :(得分:0)
这是一种替代方案,它看起来更轻,因为它是本机的并且通常由SecurityManager使用。要使用它,我们需要一个实用程序类,因为我们需要的方法是受保护的。
public class CallStackUtils extends SecurityManager {
static CallStackUtils sm = new CallStackUtils();
public Class[] getCallersClassesStack0() {
return getClassContext();
}
static public Class[] getCallersClassesStack() {
return sm.getCallersClassesStack0();
}
}