¿Alguien puede explicarme cómo funcionan las anotaciones internamente en Java?
Sé cómo podemos crear anotaciones personalizadas usando la biblioteca java.lang.annotation en java. Pero todavía no entiendo cómo funciona internamente, por ejemplo, la anotación @Override.
Estaré realmente agradecido si alguien pudiera explicar eso en detalle.
java
annotations
Chirag Dasani
fuente
fuente
Respuestas:
La primera distinción principal entre los tipos de anotaciones es si se usan en tiempo de compilación y luego se descartan (como
@Override
) o se colocan en el archivo de clase compilado y están disponibles en tiempo de ejecución (como Spring@Component
). Esto está determinado por la política de @Retención de la anotación. Si está escribiendo su propia anotación, deberá decidir si la anotación es útil en tiempo de ejecución (para la configuración automática, quizás) o solo en tiempo de compilación (para verificación o generación de código).Al compilar código con anotaciones, el compilador ve la anotación tal como ve otros modificadores en los elementos fuente, como modificadores de acceso (
public
/private
) ofinal
. Cuando encuentra una anotación, ejecuta un procesador de anotaciones, que es como una clase de complemento que dice que le interesa una anotación específica. El procesador de anotaciones generalmente usa la API de Reflection para inspeccionar los elementos que se están compilando y puede simplemente ejecutar comprobaciones en ellos, modificarlos o generar nuevo código para compilar.@Override
es un ejemplo del primero; usa la API de Reflection para asegurarse de que puede encontrar una coincidencia para la firma del método en una de las superclases y usaMessager
para causar un error de compilación si no puede.Hay una serie de tutoriales disponibles sobre cómo escribir procesadores de anotaciones; aquí hay uno útil . Busque en los métodos de la
Processor
interfaz cómo el compilador invoca un procesador de anotaciones; la operación principal tiene lugar en elprocess
método, que se llama cada vez que el compilador ve un elemento que tiene una anotación coincidente.fuente
Además de lo que otros sugirieron, te recomiendo que escribas una anotación personalizada y su procesador desde cero para ver cómo funciona la anotación.
En el mío, por ejemplo, he escrito una anotación para comprobar si los métodos están sobrecargados en tiempo de compilación.
En primer lugar, cree una anotación con el nombre
Overload
. Esta anotación se aplica al método, así que lo anoto con@Target(value=ElementType.METHOD)
package gearon.customAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target(value=ElementType.METHOD) public @interface Overload { }
A continuación, cree el procesador correspondiente para manejar los elementos anotados por la anotación definida. Para el método anotado por
@Overload
, su firma debe aparecer más de una vez. O se imprime el error.package gearon.customAnnotation; import java.util.HashMap; import java.util.Map.Entry; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic.Kind; @SupportedAnnotationTypes("gearon.customAnnotation.Overload") public class OverloadProcessor extends AbstractProcessor{ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { // TODO Auto-generated method stub HashMap<String, Integer> map = new HashMap<String, Integer>(); for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){ String signature = element.getSimpleName().toString(); int count = map.containsKey(signature) ? map.get(signature) : 0; map.put(signature, ++count); } for(Entry<String, Integer> entry: map.entrySet()){ if(entry.getValue() == 1){ processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() + " has not been overloaded"); } } return true; } }
Después de empaquetar la anotación y su proceso en un archivo jar, cree una clase
@Overload
y use javac.exe para compilarla.import gearon.customAnnotation.Overload; public class OverloadTest { @Overload public static void foo(){ } @Overload public static void foo(String s){ } @Overload public static void nonOverloadedMethod(){ } }
Dado que en
nonOverloadedMethod()
realidad no se ha sobrecargado, obtendremos el resultado como se muestra a continuación:fuente
OverloadProcessor::process
¿por qué esentry.getValue() == 1
? No es necesario agregar una anotación en la clase / interfaz principal, porroundEnv.getElementsAnnotatedWith(Overload.class)
lo que no obtendrá la clase / interfaz principal, ¿verdad?Aquí está
@Override
: http://www.docjar.com/html/api/java/lang/Override.java.html .No tiene nada de especial que lo diferencie de una anotación que podría escribir usted mismo. Las partes interesantes están en los consumidores de las anotaciones. Para una anotación como
@Override
, eso estaría en el propio compilador de Java, o en una herramienta de análisis de código estático, o en su IDE.fuente
@Override
(u otras anotaciones estándar).Básicamente, las anotaciones son solo marcadores que lee el compilador o la aplicación. Dependiendo de su política de retención, están disponibles solo en tiempo de compilación o se pueden leer en tiempo de ejecución mediante reflexión.
Muchos marcos utilizan la retención en tiempo de ejecución, es decir, comprueban de forma reflexiva si algunas anotaciones están presentes en una clase, método, campo, etc. y hacen algo si la anotación está presente (o no). Además, los miembros de las anotaciones se pueden utilizar para transmitir más información.
fuente
Siga este enlace . Esto proporcionará una respuesta cercana a su problema. Si nos centramos en las anotaciones en
Java
, las anotaciones se introdujeron en Java 5 y no son específicas de Spring. En general, las anotaciones le permiten agregar metadatos a una clase, método o variable. Una anotación puede ser interpretada por el compilador (por ejemplo, la anotación @Override) o por un marco como spring (por ejemplo, la anotación @Component).Además estoy agregando más referencias.
fuente
Incluso yo buscaba la respuesta a la misma pregunta. el enlace de abajo proporcionó el material bueno consolidado para obtener el interior de las anotaciones. https://dzone.com/articles/how-annotations-work-java ¡ Espero que te ayude!
fuente