运行时注解处理
使用反射在运行时读取注解,以实现验证、路由或注入逻辑
运行时注解处理 是 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. ValidisAnnotationPresent
在读取注解值之前,使用 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 反馈 — 无需本地设置。
此课程中的所有课时
- 定义注解:元素与默认值
- 保留策略与目标类型
- 运行时注解处理
- 编译时注解处理器