См. Java-аннотации о вызове метода - PullRequest
5 голосов
/ 18 декабря 2011

Допустим, у меня есть такая ситуация:

public String method(String s) {
    return stringForThisVisibility(s, EnumVisibility.PUBLIC);
}

и я хочу заменить его на аннотацию, подобную этой:

@VisibilityLevel(value = EnumVisibility.PUBLIC)
public String method(String s) {
    return stringForThisVisibility(s);
}

Это, кажется, лучшее и более ясное решение, но мне нужно, чтобы метод stringForThisVisibility знал значение @VisibilityLevel с некоторым отражением. Это возможно? Могу ли я увидеть аннотации к методу, вызывающему stringForThisVisibility?

Ответы [ 3 ]

8 голосов
/ 20 марта 2012

Со следующим классом:

 /**
   * Proper use of this class is
   *     String testName = (new Util.MethodNameHelper(){}).getName();
   *  or
   *     Method me = (new Util.MethodNameHelper(){}).getMethod();
   * the anonymous class allows easy access to the method name of the enclosing scope.
   */
  public static class MethodNameHelper {
    public String getName() {
      final Method myMethod = this.getClass().getEnclosingMethod();
      if (null == myMethod) {
        // This happens when we are non-anonymously instantiated
        return this.getClass().getSimpleName() + ".unknown()"; // return a less useful string
      }
      final String className = myMethod.getDeclaringClass().getSimpleName();
      return className + "." + myMethod.getName() + "()";
    }

    public Method getMethod() {
      return this.getClass().getEnclosingMethod();
    }
  }

Можно вызвать: Метод me = (new Util.MethodNameHelper () {}). GetMethod ();

Я широко используювызов getName () в этом классе.На моей машине эти экземпляры анонимных классов плюс вызовы методов, как правило, стоят около 1500 нс каждый.В моем тесте производительности подход с использованием StackElement обходится моей машине примерно в 30 раз дороже (47000 нс).

6 голосов
/ 18 декабря 2011

да, вы могли бы. что-то вроде

StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Class callerClass = Class.forName(stack[stack.length-2].getClassName());
callerClass.isAnnotationPresent(...)

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

5 голосов
/ 18 декабря 2011

Вам необходимо получить объект Method, который представляет метод, вызвавший stringForThisVisibility.К сожалению, Java не предлагает эту функциональность "из коробки".

Однако мы все еще можем получить Method через информацию, возвращаемую Thread.currentThread().getStackTrace().Этот метод возвращает массив объектов StackTraceElement.Каждый StackTraceElement объект говорит нам три вещи:

Можетнемного поэкспериментируйте, но вы должны найти, какой индекс в этом массиве представляет интересующий вас метод (вероятно, это будет первый, второй или третий StackTraceElement в массиве).

Как только вы получитежелаемый StackTraceElement, вы можете получить соответствующий ему Method объект, используя технику из моего ответа на вопрос, озаглавленный "Получить метод вызывающего абонента (java.lang.reflect.Method)" ,Эта техника все еще будет называться, даже если у класса более одного метода с таким именем.Существуют более простые приемы, если вы не беспокоитесь об этом сценарии.

Если у вас есть объект Method, достаточно просто вызвать method.getAnnotation(VisibilityLevel.class).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...