0Pricing
Java Academy · 课时

运行时注解处理

使用反射在运行时读取注解,以实现验证、路由或注入逻辑

运行时注解处理 是 CoddyKit 上的免费 Java Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

读取类级别的注解

使用 Class.getAnnotation() 读取单个类注解,或使用 getAnnotations() 读取全部类注解。如果注解不存在,则返回 null。

@Service
@RequestMapping("/api")
public class UserController {}

RequestMapping rm = UserController.class.getAnnotation(RequestMapping.class);
if (rm != null) System.out.println(Arrays.toString(rm.value())); // ["/api"]

读取方法注解

通过 method.getAnnotation() 获取方法注解。遍历 getDeclaredMethods(),即可扫描类中的所有方法。

for (Method m : UserController.class.getDeclaredMethods()) {
    GetMapping gm = m.getAnnotation(GetMapping.class);
    if (gm != null) System.out.println(m.getName() + " -> " + Arrays.toString(gm.value()));
}

读取字段注解

验证和 ORM 框架会使用字段注解。遍历 getDeclaredFields(),并检查每个相关注解。

for (Field f : User.class.getDeclaredFields()) {
    Column col = f.getAnnotation(Column.class);
    if (col != null) System.out.println(f.getName() + " -> column: " + col.name());
}

读取参数注解

可以通过 method.getParameterAnnotations() 获取参数注解。它返回一个二维数组:每一行对应一个参数,每个元素对应一个注解。

Method m = UserController.class.getDeclaredMethod("create", UserDto.class);
Annotation[][] pa = m.getParameterAnnotations();
for (Annotation a : pa[0]) System.out.println(a.annotationType().getSimpleName()); // e.g. Valid

isAnnotationPresent

在读取注解值之前,使用 isAnnotationPresent(AnnotationType.class) 进行快速且安全的空值检查。

if (m.isAnnotationPresent(Transactional.class)) {
    beginTransaction();
    m.invoke(target, args);
    commitTransaction();
}

构建简单的依赖注入容器

扫描包含 @Component 注解的类,使用反射实例化这些类,并将实例存储在映射中,从而构建一个简化版的 Spring 容器。

Map<Class<?>, Object> beans = new HashMap<>();
for (Class<?> cls : scanPackage("com.example")) {
    if (cls.isAnnotationPresent(Component.class)) {
        beans.put(cls, cls.getDeclaredConstructor().newInstance());
    }
}

注入带有 @Inject 注解的字段

构造 Bean 后,扫描带有 @Inject 注解的字段,并使用反射为其设置值,从而模拟字段注入。

for (Object bean : beans.values()) {
    for (Field f : bean.getClass().getDeclaredFields()) {
        if (f.isAnnotationPresent(Inject.class)) {
            f.setAccessible(true);
            f.set(bean, beans.get(f.getType()));
        }
    }
}

使用注解值进行运行时验证

读取约束注解的值(例如 @Range(min=1, max=100)),并在运行时根据这些值验证字段值。

for (Field f : dto.getClass().getDeclaredFields()) {
    Range range = f.getAnnotation(Range.class);
    if (range != null) {
        f.setAccessible(true);
        int val = (int) f.get(dto);
        if (val < range.min() || val > range.max())
            throw new ValidationException(f.getName() + " out of range");
    }
}

读取可重复注解

对于 @Repeatable 注解,使用 getAnnotationsByType() 以透明方式从容器注解中获取所有实例。

Tag[] tags = MyClass.class.getAnnotationsByType(Tag.class);
for (Tag t : tags) System.out.println(t.value());

使用 ClassPath 库扫描包

标准 Java 反射无法列出包中的所有类。请使用 Reflections、ClassGraph 或 Spring 的 ClassPathScanningCandidateComponentProvider 等库,扫描类路径条目。

Reflections reflections = new Reflections("com.example.service");
Set<Class<?>> services = reflections.getTypesAnnotatedWith(Service.class);
services.forEach(System.out::println);

运行时注解处理:总结

运行时注解处理支持依赖注入、验证、路由和 ORM。它属于初始化阶段的工作:在启动时处理一次注解,缓存结果,并避免在每次请求的路径中使用反射。

快速检查

哪个方法可以获取 @Repeatable 注解的所有实例?

回顾

使用 getAnnotation/isAnnotationPresent 处理单个注解。使用 getDeclared* 扫描方法和字段。使用 getAnnotationsByType 处理可重复注解。在启动时完成处理,并缓存结果。

常见问题解答

「运行时注解处理」课时是免费的吗?

是的 — 「运行时注解处理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「运行时注解处理」这节课中我会学到什么?

使用反射在运行时读取注解,以实现验证、路由或注入逻辑 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「运行时注解处理」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 定义注解:元素与默认值
  2. 保留策略与目标类型
  3. 运行时注解处理
  4. 编译时注解处理器
← 返回 Java Academy