三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

497. Java 反射 - 使用反射读取注解

497. Java 反射 - 使用反射读取注解

文章目录

  • 497. Java 反射 - 使用反射读取注解
    • 1. 为什么要关心注解?
    • 2. 获取注解的工具类:`AnnotatedElement`
    • 3. 示例:类级别注解
    • 4. 示例:重复注解 (Repeatable Annotations)
      • 方式一:通过容器注解 `@Validators`
      • 方式二:直接用 `getAnnotationsByType()`
    • 5. 总结

497. Java 反射 - 使用反射读取注解

1. 为什么要关心注解?

在现代 Java 开发中,注解已经成为框架和库的“开关”。

  • ORM 框架(如 Hibernate、JPA):用注解标记实体字段和表的映射。
  • Spring:用注解实现依赖注入、事务管理、安全控制。
  • 验证框架:用注解标记参数是否允许null、是否必须符合某种格式。

👉 注解之所以能发挥作用,核心原因就是:运行时通过反射 API 读取注解并执行相应逻辑


2. 获取注解的工具类:AnnotatedElement

以下几个反射类都实现了AnnotatedElement接口:

  • Class(类、接口、枚举、记录、数组)
  • Field(字段)
  • Method(方法)
  • Constructor(构造函数)

它们提供了几组关键方法:

  • isAnnotationPresent(Class<?>):是否存在某个注解。
  • getAnnotations():获取该元素上的所有注解(包括继承的)。
  • getDeclaredAnnotations():只获取该元素本身声明的注解。
  • getAnnotation(Class<?>):获取指定类型的注解实例。
  • getAnnotationsByType(Class<?>):获取重复注解。

3. 示例:类级别注解

定义枚举和注解:

enumSerializedFormat{BINARY,XML,JSON}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interfaceBean{}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interfaceSerialized{SerializedFormatformat()defaultSerializedFormat.JSON;}

在类上使用:

@Serialized@BeanpublicclassPerson{}

通过反射读取:

Class<?>c=Person.class;booleanisBean=c.isAnnotationPresent(Bean.class);System.out.println("isBean = "+isBean);Annotation[]annotations=c.getAnnotations();for(Annotationannotation:annotations){System.out.println("annotation = "+annotation);}

输出:

isBean=trueannotation=@org.devjava.Serialized(format=JSON)annotation=@org.devjava.Bean()

👉 注意:返回的其实是注解类的实例对象,你可以直接调用它的方法。

Serializedserialized=c.getAnnotation(Serialized.class);System.out.println("format = "+serialized.format());

输出:

format=JSON

4. 示例:重复注解 (Repeatable Annotations)

定义验证规则:

enumValidationRules{NON_NULL,NON_EMPTY,NON_ZERO}@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interfaceValidators{Validator[]value();}@Target(ElementType.FIELD)@Repeatable(Validators.class)@interfaceValidator{ValidationRulesvalue();}

应用在Person类的字段上:

publicclassPerson{@Validator(ValidationRules.NON_NULL)@Validator(ValidationRules.NON_EMPTY)privateStringname;}

读取注解:

方式一:通过容器注解@Validators

FieldnameField=Person.class.getDeclaredField("name");Annotation[]annotations=nameField.getAnnotations();Validatorsvalidators=(Validators)annotations[0];for(Validatorv:validators.value()){System.out.println("validator = "+v);}

输出:

validator=@org.devjava.Validator(NON_NULL)validator=@org.devjava.Validator(NON_EMPTY)

方式二:直接用getAnnotationsByType()

Validator[]validators=nameField.getAnnotationsByType(Validator.class);for(Validatorv:validators){System.out.println("annotation = "+v);}

输出:

annotation=@org.devjava.Validator(NON_NULL)annotation=@org.devjava.Validator(NON_EMPTY)

👉 第二种方式更简洁,JDK 会自动帮你展开容器注解。


5. 总结

  • 注解是框架的“说明书”,框架通过反射读取注解来决定如何运行。
  • 类、方法、字段、构造函数都可以携带注解,并通过AnnotatedElement访问。
  • isAnnotationPresent():检查是否存在。
  • getAnnotation():获取单个注解。
  • getAnnotationsByType():用于重复注解。
← 返回列表