通过AspectJ了解调用者类

Ada*_*ent 4 java spring aspectj

我试图模仿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;
    }
}
Run Code Online (Sandbox Code Playgroud)

呼叫切入点会让我呼叫者上下文,但是这是行不通的,因为我将调用通过反射我的消息监听器的方法.在执行切入点(注释掉)不会告诉我,谁是调用方法.

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

kri*_*aex 10

实际上cheeken的答案很好,但是对于AspectJ call()切入点,你可以更轻松地获得调用类,而不会出现难看的反射:

thisEnclosingJoinPointStaticPart.getSignature().getDeclaringType()
Run Code Online (Sandbox Code Playgroud)

如果你认为它比另一个更好,请考虑接受这个答案,否则只是享受AspectJ的力量. ;-)


che*_*ken 8

您可以使用以下调用确定哪个类正在调用当前方法.请注意,您必须捕获ClassNotFoundException(除非您只是简单地将名称检索为a String).

Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
Run Code Online (Sandbox Code Playgroud)

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

  1. Thread#getStackTrace()
  2. CurrentClass.currentMethod()
  3. ParentClass.parentMethod()

  • 我认为值得一提的是,使用`Thread.currentThread().getStackTrace()`比通过`new Throwable()获取堆栈跟踪慢得多.getStackTrace()`参见http://bugs.java.com/bugdatabase /view_bug.do?bug_id=6375302 (3认同)