2012-06-07 4 views
3

Я пытаюсь подражать Spring AspectJ @Async support, но с шиной сообщений.Зная класс вызывающего абонента с AspectJ

Проблема заключается в том, что мне нужна моя шина сообщений (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; 
    } 
} 

вызова среза точек получите мне контекст вызывающего абонента, но это не будет работать, как я буду называть этот метод с моим слушателем сообщения через отражение. Выполнение pointcut (закомментировано) не скажет мне, кто вызывает этот метод.

Есть ли способ определить класс вызывающего абонента, возможно, через какой-то анализ дампа стека?

ответ

8

Вы можете определить, какой класс вызывает текущий метод со следующим вызовом. Обратите внимание, что вам придется поймать ClassNotFoundException (если только вы не удовлетворены просто получением имени как String).

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

Почему третий элемент? Поскольку стек заказан как так, когда метод трассировки стека вызывается:

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

Я понял, что это будет что-то вроде этого, но я нервничал, что это было бы непредсказуемо из-за совета AspectJ. То есть stacktrace должен игнорировать советы аспект. Я предположил, что могу просто сделать getStackTrace() [3] или getStackTrace [4] и т. Д. Через пробную версию и ошибку. –

+2

Я думаю, что стоит сказать, что использование 'Thread.currentThread(). GetStackTrace()' намного медленнее, чем получение трассировки стека через 'new Throwable(). GetStackTrace()' См. Http://bugs.java.com/ bugdatabase/view_bug.do? bug_id = 6375302 –

0

Это альтернатива, которая кажется больше света поскольку является родным и обычно используется SecurityManager. Чтобы использовать его, нам нужен класс утилиты, потому что метод, который нам нужен, защищен.

public class CallStackUtils extends SecurityManager { 

    static CallStackUtils sm = new CallStackUtils(); 

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

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

} 
7

На самом деле cheeken «s ответ хорош, но для AspectJ call() срезов в вы можете получить класс вызывающую гораздо легче и без уродливого отражения:

thisEnclosingJoinPointStaticPart.getSignature().getDeclaringType() 

Пожалуйста, обратите внимание, чтобы принять этот ответ, если вы думаете, что это лучше, чем другое, иначе просто наслаждайтесь силой AspectJ. ;-)

+0

А, спасибо, я подумал, что есть лучший способ AspectJ получить эти данные. Мне действительно нужна целая трассировка стека, а не только метод вызова. Есть ли способ для этого? Еще раз спасибо, upvote. – Faustas

+0

+1 однако, если вы внимательно прочитали мой вопрос, я вызываю метод через отражение (сродни трассировке Spring MVC), поэтому это не будет работать, поскольку эта информация не скомпилирована. –

+0

True. В этом случае получение стека вызовов с помощью нового экземпляра «Throwable» - более подходящий курс действий. – kriegaex

Смежные вопросы