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

文章目录

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

定义枚举和注解:

java 复制代码
enum SerializedFormat { BINARY, XML, JSON }

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Bean {}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Serialized {
    SerializedFormat format() default SerializedFormat.JSON;
}

在类上使用:

java 复制代码
@Serialized
@Bean
public class Person {}

通过反射读取:

java 复制代码
Class<?> c = Person.class;

boolean isBean = c.isAnnotationPresent(Bean.class);
System.out.println("isBean = " + isBean);

Annotation[] annotations = c.getAnnotations();
for (Annotation annotation : annotations) {
    System.out.println("annotation = " + annotation);
}

输出:

java 复制代码
isBean = true
annotation = @org.devjava.Serialized(format=JSON)
annotation = @org.devjava.Bean()

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

java 复制代码
Serialized serialized = c.getAnnotation(Serialized.class);
System.out.println("format = " + serialized.format());

输出:

java 复制代码
format = JSON

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

定义验证规则:

java 复制代码
enum ValidationRules { NON_NULL, NON_EMPTY, NON_ZERO }

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Validators {
    Validator[] value();
}

@Target(ElementType.FIELD)
@Repeatable(Validators.class)
@interface Validator {
    ValidationRules value();
}

应用在 Person 类的字段上:

java 复制代码
public class Person {
    @Validator(ValidationRules.NON_NULL)
    @Validator(ValidationRules.NON_EMPTY)
    private String name;
}

读取注解:

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

java 复制代码
Field nameField = Person.class.getDeclaredField("name");
Annotation[] annotations = nameField.getAnnotations();
Validators validators = (Validators) annotations[0];
for (Validator v : validators.value()) {
    System.out.println("validator = " + v);
}

输出:

java 复制代码
validator = @org.devjava.Validator(NON_NULL)
validator = @org.devjava.Validator(NON_EMPTY)

方式二:直接用 getAnnotationsByType()

java 复制代码
Validator[] validators = nameField.getAnnotationsByType(Validator.class);
for (Validator v : validators) {
    System.out.println("annotation = " + v);
}

输出:

java 复制代码
annotation = @org.devjava.Validator(NON_NULL)
annotation = @org.devjava.Validator(NON_EMPTY)

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


5. 总结

  • 注解是框架的"说明书",框架通过反射读取注解来决定如何运行。
  • 类、方法、字段、构造函数 都可以携带注解,并通过 AnnotatedElement 访问。
  • isAnnotationPresent():检查是否存在。
  • getAnnotation():获取单个注解。
  • getAnnotationsByType():用于重复注解。
相关推荐
kruptos1 小时前
分布式系统怎么“选主“?Raft 共识一次讲清
开发语言·分布式·php·共识算法
xcl09251 小时前
幼儿托育系统开发实战:从需求分析到上线全流程指南
java·大数据·需求分析
吴声子夜歌2 小时前
ApacheCommons——commons-cli(命令行参数解析)
java·开发语言·apache
小小猪的春天2 小时前
Java 手写第一个 MCP Server:Spring AI MCP 半小时跑通
java·人工智能·spring boot·ai编程
find1star2 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
今天AI了吗3 小时前
DeepSeek Harness 深度解析:从评测架构到实战落地
java·网络·数据库·人工智能·架构·java-ee
benchmark_cc3 小时前
REST API 和 Python SDK 应该怎么选?量化交易数据接口选型实战
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
王的宝库3 小时前
Go 项目结构:从单文件到标准工程布局
开发语言·后端·golang
Tairitsu_H3 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
许彰午3 小时前
27-AuthService登录链路
java·低代码·架构