Knowing caller class with AspectJ

寵の児 提交于 2020-01-13 11:24:09

问题


I'm trying to imitate Spring's AspectJ @Async support but with a message bus.

The issue is I need to know if my Message Bus (RabbitMQ MessageListener) is calling the method or a normal (all others) caller where the method will return instantly.

My annotation is called @MQAsync instead of 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;
    }
}

The call pointcut will get me the caller context but that will not work as I will be calling the method with my message listener through reflection. The execution pointcut (commented out) will not tell me who is calling the method.

Is there a way to determine the caller class maybe through some sort of stack dump analysis?


回答1:


You can determine which class is invoking the current method with the following call. Note that you'll have to catch ClassNotFoundException (unless you're satisfied simply retrieving the name as a String).

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

Why the third element? Because the stack is ordered like so when the stack trace method is invoked:

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



回答2:


Actually cheeken's answer is nice, but for AspectJ call() pointcuts you can get the calling class much more easily and without ugly reflection:

thisEnclosingJoinPointStaticPart.getSignature().getDeclaringType()

Please consider to accept this answer if you think it is better than the other one, otherwise just enjoy the power of AspectJ. ;-)




回答3:


This is an alternative that seems more light since is native and commonly used by the SecurityManager. To use it we need a utility class because the the method we need is protected.

public class CallStackUtils extends SecurityManager {

  static CallStackUtils sm = new CallStackUtils();

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

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

}


来源:https://stackoverflow.com/questions/10924675/knowing-caller-class-with-aspectj

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!