2009-11-26 12 views
29

¿Cómo puedo recuperar el valor de una anotación en el método anotado ??Recuperar el atributo de anotación Java

que tengo:

@myAnnotation(attribute1 = value1, attibute2 = value2) 
public void myMethod() 
{ 
    //I want to get value1 here 
} 
+0

¿Puede proporcionar más detalles sobre lo que está tratando de lograr? – Carl

+0

Es justo como dije, quiero usar el valor de attribute1 sin tener que repetirlo en el código –

+0

No es realmente un método de programación efectivo. Aquí no tiene ninguna ventaja tener los valores establecidos en una anotación en lugar de establecerlos en variables finales dentro del código, o establecerse en variables estáticas finales fuera del método. – Jherico

Respuesta

43
  1. Obtener Method ejemplo.
  2. Obtener anotación.
  3. Obtiene el valor del atributo de anotación.

Algo así como:

Method m = getClass().getMethod("myMethod"); 
MyAnnotation a = m.getAnnotation(MyAnnotation.class); 
MyValueType value1 = a.attribute1(); 

Tendrá que coger/manejar las excepciones apropiadas, por supuesto. Lo anterior supone que está hecho recuperando método de la clase actual (sustituir getClass() con Class.forName() lo contrario) y el método en cuestión es pública (uso getDeclaredMethods() si eso no es el caso)

cosas
+0

no debería ser "MyValueType value1 = a.getAttribute1();" –

+0

o más como "a.attribute()' – Bozho

+0

Ciertamente debería haberlo hecho. Gracias, editado – ChssPly76

19

Dos importantes:

  • Hay es no hay manera de obtener el método actual, por ejemplo no hay getMethod() como getClass(). Por lo tanto, el método de acceso a su propia anotación necesitaría saber su propio nombre.
  • La política de retención de la anotación debe establecerse en RUNTIME, para que pueda acceder a la anotación en el tiempo de ejecución. El valor predeterminado es el tiempo de compilación, lo que significa que las anotaciones están disponibles en el archivo de la clase, pero no se puede acceder en tiempo de ejecución mediante la reflexión.

ejemplo completo:

@Retention(RetentionPolicy.RUNTIME) 
public static @interface MyAnnotation { 
    String value1(); 

    int value2(); 
} 

@Test 
@MyAnnotation(value1 = "Foo", value2 = 1337) 
public void testAnnotation() throws Exception { 
    Method[] methods = getClass().getMethods(); 
    Method method = methods[0]; 
    assertEquals("testAnnotation", method.getName()); 
    MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); 
    assertEquals("Foo", annotation.value1()); 
    assertEquals(1337, annotation.value2()); 
} 
+4

Hay una forma de obtener el método actual. O bien 'Thread.currentThread(). getStackTrace() [2] .getMethodName() 'o' new Throwable(). FillInStackTrace(). GetStackTrace() [0].getMethodName() 'debería hacerlo. – ChssPly76

+1

+1 por mencionar Retención – basszero

+1

@ ChssPly76, la construcción de una stacktrace no es del todo confiable, ya que los javadocs mencionan: "Algunas máquinas virtuales pueden, en algunas circunstancias, omitir uno o más marcos de pila de la pila. En el caso extremo, una máquina virtual que no tiene información de rastreo de pila [...] puede devolver una matriz de longitud cero desde este método ". – gustafc

1

@mhaller: un poco demasiado largo para un comentario en su entrada. Obviamente sería necesario un mayor refinamiento para hacer frente a métodos sobrecargados, pero no es imposible .:

import java.lang.reflect.Method; 

public class Hack { 
    public static void main (String[] args) { 
     (new Hack()).foobar(); 
    } 
    public void foobar() { 
     Method here = getCurrentMethod(this); 
     System.out.format("And here we are: %s\n", here); 
    } 
    public static final Method getCurrentMethod(Object o) { 
     String s = Thread.currentThread().getStackTrace()[2].getMethodName(); 
     Method cm = null; 
     for(Method m : o.getClass().getMethods()){ 
      if(m.getName().equals(s)){ 
       cm = m; break; 
      } 
     } 
     return cm; 
    } 
} 

[editar: crédito/gracias a Alexandr Priymak para detectar el error en main()]

+3

Tengo la sensación de que si realmente hace esto en el código de producción, convoca a los Grandes Antiguos para devorar su propia alma. –

+0

@Skip Head - ¿por qué? Hay dos cosas que debe tener cuidado aquí: (1) el índice de matriz ** en teoría ** puede ser diferente de 2 en algunas JVM, pero eso es fácil de solucionar al recorrer toda la traza; (2) esto no funcionará para métodos sobrecargados; puedes hacer un poco de magia negra con javassist para adivinar cuál es la correcta según el número de línea, pero eso realmente es algo dudoso. Aparte de eso, funciona perfectamente: ¿cómo crees que funcionan los rastros de pila? – ChssPly76

+0

@ ChssPly76: no es necesario recorrer todo el trazado. El método de rastreo comienza en la parte superior y camina hasta que se encuentra. Y la persona que llama es la siguiente. – alphazero

0

Para obtener el método actual, intente utilizar este código:

Thread.currentThread().getStackTrace()[1].getClassName().toString()+\".\"+Thread.currentThread().getStackTrace()[1].getMethodName().toString() 
Cuestiones relacionadas