注解与反射基础¶
这一章是读懂 Spring 的钥匙。Spring 里到处是 @:@RestController、@Service、@Autowired、@RequestMapping……它们怎么起作用的?答案就是注解 + 反射。
注解 = 代码的"标签"¶
注解本身什么都不做,它只是个标签。真正干活的是"读这个标签的程序"。比如:
- 编译器读
@Override帮你检查重写对不对; - Spring 读
@RestController知道"这个类要当成接口处理器注册"; - MyBatis-Plus 读
@Table知道"这个类对应哪张表"。
自定义注解¶
@Retention(RetentionPolicy.RUNTIME) // 关键:运行时保留,反射才能读到
@Target(ElementType.TYPE) // 只能贴在类上
@interface Table {
String name(); // 注解属性
}
@Retention 决定注解活多久
SOURCE:只存在于源码,编译后丢弃(如@Override)。CLASS:保留到 class 文件,但运行时读不到(默认)。RUNTIME:运行时可通过反射读到。Spring 的注解基本都是这个。
反射:运行时窥探类¶
Class<?> clazz = User.class;
clazz.getSimpleName(); // 类名
clazz.getDeclaredFields(); // 所有字段
clazz.getAnnotation(Table.class); // 读取注解
clazz.isAnnotationPresent(Table.class); // 是否有这个注解
Spring 的核心套路(剧透)¶
flowchart LR
A["你写 @RestController\n@Service @Autowired"] --> B["Spring 启动时用反射扫描这些注解"]
B --> C["自动创建对象、注入依赖、注册路由"]
C --> D["你什么都不用 new,直接能用"]
你贴注解 → Spring 用反射读注解 → 自动帮你干活。 这就是"控制反转 / 依赖注入"(第 20 章),也是注解和反射存在的最大意义。
完整可运行示例¶
package com.javaglm.language.ch18;
import java.lang.annotation.*;
import java.lang.reflect.Field;
/**
* 第 18 章 · 注解与反射基础 —— Spring 的灵魂。
* 注解(@):给代码贴"标签",本身不做事,靠"别人"去读它。
* 反射:运行时动态拿到类的字段/方法/注解信息。
* Spring 的 @RestController / @Autowired 底层就是:用反射扫描注解,然后干活。
*/
public class AnnotationReflectionDemo {
public static void main(String[] args) {
// 1. 反射:运行时拿到类的结构信息
Class<?> clazz = User.class;
System.out.println("类名 = " + clazz.getSimpleName());
for (Field f : clazz.getDeclaredFields()) {
System.out.println(" 字段 = " + f.getName() + " : " + f.getType().getSimpleName());
}
// 2. 读取类上的自定义注解(这是 Spring 框架的核心套路)
if (clazz.isAnnotationPresent(Table.class)) {
Table table = clazz.getAnnotation(Table.class);
System.out.println("User 映射的表名 = " + table.name());
}
}
}
/** 自定义注解:标记实体对应的数据库表名。 */
@Retention(RetentionPolicy.RUNTIME) // 必须 RUNTIME,反射才能读到
@Target(ElementType.TYPE) // 只能贴在类上
@interface Table {
String name(); // 注解的"属性",用法像方法
}
/** 用注解标记:这个类对应数据库表 t_user。 */
@Table(name = "t_user")
class User {
private Long id;
private String username;
}
:octicons-arrow-left-16: 上一章:IO 与文件基础 | 下一章:多线程入门