java - introspección - para que sirven las anotaciones
¿Es posible leer el valor de una anotación en java? (7)
este es mi código:
@Column(columnName="firstname")
private String firstName;
@Column(columnName="lastname")
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
¿es posible leer el valor de mi anotación @Column ( columnName = "xyz123") en otra clase?
Atendiendo a la respuesta de @ Cefalópodo, si desea todos los nombres de columna en una lista, puede usar este delineador:
List<String> columns =
Arrays.asList(MyClass.class.getFields())
.stream()
.filter(f -> f.getAnnotation(Column.class)!=null)
.map(f -> f.getAnnotation(Column.class).columnName())
.collect(Collectors.toList());
En el caso común, tiene acceso privado para los campos, por lo que NO PUEDE usar getFields en la reflexión. En lugar de esto, debes usar getDeclaredFields
Entonces, en primer lugar, debe saber si su anotación de Columna tiene la retención en tiempo de ejecución:
@Retention(RetentionPolicy.RUNTIME)
@interface Column {
}
Después de eso, puedes hacer algo como esto:
for (Field f: MyClass.class.getDeclaredFields()) {
Column column = f.getAnnotation(Column.class);
// ...
}
Obviamente, le gustaría hacer algo con el campo: establezca un nuevo valor usando el valor de la anotación:
Column annotation = f.getAnnotation(Column.class);
if (annotation != null) {
new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
object,
myCoolProcessing(
annotation.value()
)
);
}
Entonces, el código completo se puede ver así:
for (Field f : MyClass.class.getDeclaredFields()) {
Column annotation = f.getAnnotation(Column.class);
if (annotation != null)
new PropertyDescriptor(f.getName(), Column.class).getWriteMethod().invoke(
object,
myCoolProcessing(
annotation.value()
)
);
}
Nunca lo hice, pero parece que Reflection proporciona. Field
es un elemento AnnotatedElement
y, por lo tanto, tiene getAnnotation
. Esta página tiene un ejemplo (copiado a continuación); bastante sencillo si conoce la clase de la anotación y si la política de anotación retiene la anotación en tiempo de ejecución. Naturalmente, si la política de retención no mantiene la anotación en tiempo de ejecución, no podrá consultarla en tiempo de ejecución.
Una respuesta que se ha eliminado desde entonces (?) Proporcionó un enlace útil a un tutorial de anotaciones que puede resultar útil; Copié el enlace aquí para que la gente pueda usarlo.
Ejemplo de esta página :
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnno {
String str();
int val();
}
class Meta {
@MyAnno(str = "Two Parameters", val = 19)
public static void myMeth(String str, int i) {
Meta ob = new Meta();
try {
Class c = ob.getClass();
Method m = c.getMethod("myMeth", String.class, int.class);
MyAnno anno = m.getAnnotation(MyAnno.class);
System.out.println(anno.str() + " " + anno.val());
} catch (NoSuchMethodException exc) {
System.out.println("Method Not Found.");
}
}
public static void main(String args[]) {
myMeth("test", 10);
}
}
Por supuesto que es. Aquí hay una anotación de muestra:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
String testText();
}
Y un ejemplo de método anotado:
class TestClass {
@TestAnnotation(testText="zyx")
public void doSomething() {}
}
Y un método de muestra en otra clase que imprime el valor de testText:
Method[] methods = TestClass.class.getMethods();
for (Method m : methods) {
if (m.isAnnotationPresent(TestAnnotation.class)) {
TestAnnotation ta = m.getAnnotation(TestAnnotation.class);
System.out.println(ta.testText());
}
}
No es muy diferente para las anotaciones de campo como la tuya.
Cheerz!
Sí, si su anotación de Columna tiene la retención de tiempo de ejecución
@Retention(RetentionPolicy.RUNTIME)
@interface Column {
....
}
puedes hacer algo como esto
for (Field f: MyClass.class.getFields()) {
Column column = f.getAnnotation(Column.class);
if (column != null)
System.out.println(column.columnName());
}
Si bien todas las respuestas dadas hasta ahora son perfectamente válidas, también se debe tener en cuenta la biblioteca de reflexiones de google para un enfoque más genérico y fácil para el escaneo de anotaciones, por ejemplo
Reflections reflections = new Reflections("my.project.prefix");
Set<Field> ids = reflections.getFieldsAnnotatedWith(javax.persistence.Id.class);
También puede usar tipos genéricos, en mi caso, teniendo en cuenta todo lo dicho antes de que pueda hacer algo como:
public class SomeTypeManager<T> {
public SomeTypeManager(T someGeneric) {
//That''s how you can achieve all previously said, with generic types.
Annotation[] an = someGeneric.getClass().getAnnotations();
}
}
Recuerde que esto no equivaldrá al 100% de SomeClass.class.get (...) ();
Pero puede hacer el truco ...