chirag dasani
¿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é muy agradecido si alguien pudiera explicar eso en detalle.
La primera distinción principal entre los tipos de anotación es si se usan en tiempo de compilación y luego se descartan (como @Override
) o colocado en el archivo de clase compilado y disponible en tiempo de ejecución (como Spring’s @Component
). Esto está determinado por el @Retencion política de la anotación. Si está escribiendo su propia anotación, debe decidir si la anotación es útil en tiempo de ejecución (quizás para la configuración automática) 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 del mismo modo que ve otros modificadores en los elementos fuente, como los modificadores de acceso (public
/private
) o final
. Cuando encuentra una anotación, ejecuta un procesador de anotaciones, que es como una clase de complemento que dice que está interesada en 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 controles en ellos, modificarlos o generar código nuevo para compilar. @Override
es un ejemplo del primero; utiliza la API de Reflection para asegurarse de que puede encontrar una coincidencia para la firma del método en una de las superclases y utiliza el Messager
para causar un error de compilación si no puede.
Hay varios tutoriales disponibles sobre cómo escribir procesadores de anotaciones; aquí hay uno útil. Mire a través de los métodos en la Processor
interfaz para saber cómo el compilador invoca un procesador de anotaciones; la operación principal tiene lugar en el process
método, que se llama cada vez que el compilador ve un elemento que tiene una anotación coincidente.
-
sería bueno señalarnos exactamente cómo el procesador de anotaciones de Spring analiza el @Componente e inyecta la clase en su contenedor
-Junchen Liu
18 mayo 2016 a las 14:32
-
@shanyangqu Eso está fuera de tema para la pregunta, que no es específica de Spring. Puede leer las clases del posprocesador usted mismo.
– chrylis -cautelosamente optimista-
18 mayo 2016 a las 14:39
eugenio
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 verificar si los métodos están sobrecargados en tiempo de compilación.
En primer lugar, cree una anotación llamada Overload
. Esta anotación se aplica al método, así que la 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 con @Overload
y use javac.exe para compilarlo.
import gearon.customAnnotation.Overload;
public class OverloadTest {
@Overload
public static void foo(){
}
@Overload
public static void foo(String s){
}
@Overload
public static void nonOverloadedMethod(){
}
}
Ya que nonOverloadedMethod()
en realidad no se ha sobrecargado, obtendremos el resultado como se muestra a continuación:
-
La información anterior es muy buena con respecto a JDK6 (+1 para eso), pero ¿cómo lograr lo mismo usando JDK5 también? Usando JDK6 SupportedAnnotationTypes, la clase AbstractProcessor se volvió más simple, pero ¿cómo sucedió lo mismo en el pasado (como Spring FrameWork 2.5 en jdk5)? ¿Cómo JVM detecta el procesador de anotaciones como la clase en jdk5? ¿Puede guiarse editando la respuesta en 2 secciones (una para JDK5, la versión actual es para Jdk6 +)?
– prajitgandhi
29 de enero de 2017 a las 19:12
-
En tu clase
OverloadProcessor::process
porque esentry.getValue() == 1
? No es necesario agregar una anotación en la clase/interfaz principal, por lo queroundEnv.getElementsAnnotatedWith(Overload.class)
no obtendrá la clase/interfaz principal, ¿verdad?– VimNing
16 de octubre de 2019 a las 2:51
-
Estoy confundido en esta parte, pero creo que su respuesta es muy útil.
– VimNing
16 de octubre de 2019 a las 2:54
-
@s̮̦̩e̝͓c̮͔̞ṛ̖̖e̬̣̦t̸͉̥̳̼ Si un método se trata como sobrecarga, debe haber al menos otro método con el mismo nombre definido en la clase.
– Eugenio
16 de octubre de 2019 a las 3:11
-
@Raining para que un método diga Sobrecargado, debe aparecer más de una vez en la misma clase, pero si es ` == 1`, entonces es un error.
– KrishPrabakar
17 de junio de 2020 a las 14:02
Aquí está @Override
: http://www.docjar.com/html/api/java/lang/Override.java.html.
No tiene nada especial que lo diferencie de una anotación que podría escribir usted mismo. Las partes interesantes están en el 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.
-
Conozco el código fuente de la anotación Anular. Pero cómo funciona internamente. ¿Cómo se puede identificar que este método no es un método de anulación o este es un método de anulación? ¿O puedo crear mi anotación de anulación personalizada? y debería funcionar exactamente con el mismo comportamiento que la anotación de anulación de Java
– Chirag Dasani
13 de agosto de 2013 a las 6:31
-
Como dije en mi respuesta, el comportamiento no es parte de la anotación. La interpretación está en las cosas que consumen la anotación. Por eso, a menos que cambie el consumidor, prácticamente no puede crear su propia versión personalizada de
@Override
(u otras anotaciones estándar).– bola mate
13 de agosto de 2013 a las 13:55
Básicamente, las anotaciones son solo marcadores que lee el compilador o la aplicación. Según 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 la reflexión.
Muchos marcos utilizan la retención en tiempo de ejecución, es decir, comprueban reflexivamente 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 usar para pasar más información.
Ruchira Gayan Ranaweera
Sigue esto 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.
-
@LuiggiMendoza java 1.7 documento de anotaciones agregado
– Ruchira Gayan Ranaweera
12 de agosto de 2013 a las 16:44
-
@Ruchira abrí todos los enlaces pero aún no tengo claro cómo funciona. ¿Puedes explicarme en detalles como considerar como anotaciones de primavera? Puedo hacer todas las cosas usando anotaciones sin escribir ninguna configuración en el archivo spring.xml. ¿Se vincula internamente la anotación a la configuración xml?
– Chirag Dasani
13 de agosto de 2013 a las 6:50
-
@ChiragDasani echa un vistazo a esto. esto puede ayudarte static.springsource.org/spring/docs/3.0.0.M3/reference/html/… y también vea esta publicación SO stackoverflow.com/questions/2798181/…
– Ruchira Gayan Ranaweera
13 de agosto de 2013 a las 6:53
Kusum
Incluso yo estaba buscando la respuesta de la misma pregunta. el siguiente enlace proporcionó las cosas buenas consolidadas para obtener el interior de las anotaciones. https://dzone.com/articles/how-annotations-work-java
¡Espero eso ayude!
-
@LuiggiMendoza java 1.7 documento de anotaciones agregado
– Ruchira Gayan Ranaweera
12 de agosto de 2013 a las 16:44
-
@Ruchira abrí todos los enlaces pero aún no tengo claro cómo funciona. ¿Puedes explicarme en detalles como considerar como anotaciones de primavera? Puedo hacer todas las cosas usando anotaciones sin escribir ninguna configuración en el archivo spring.xml. ¿Se vincula internamente la anotación a la configuración xml?
– Chirag Dasani
13 de agosto de 2013 a las 6:50
-
@ChiragDasani echa un vistazo a esto. esto puede ayudarte static.springsource.org/spring/docs/3.0.0.M3/reference/html/… y también vea esta publicación SO stackoverflow.com/questions/2798181/…
– Ruchira Gayan Ranaweera
13 de agosto de 2013 a las 6:53
¿A qué te refieres con “trabajar internamente”? El compilador? ¿El tiempo de ejecución?
– chrylis -cautelosamente optimista-
12 de agosto de 2013 a las 14:45
@chrylis Work internamente significa cómo se identifica automáticamente que este método es un método de anulación o este no es un método de anulación. Es trabajo en ambos tiempos. como anular el trabajo de anotación en tiempo de compilación y la anotación del controlador de primavera funciona en tiempo de ejecución
– Chirag Dasani
13 de agosto de 2013 a las 6:45