代码语言

知识点思维导图

29 个知识节点

Java(08) - 注解与反射

读完后,你应能完成以下任务:

  • 绘制“Java(08) - 注解与反射 / 注解是什么?”的关键对象与数据流,解释“注解就是代码里的 @xxx 标记。”,并用源码位置、日志或 Trace 标注证据。
  • 为“Java(08) - 注解与反射 / 用前端类比理解”设计正常与异常输入,验证“或者更通俗的类比:注解像快递单上的标签——"易碎"、"加急"、"冷藏"。”,输出首个偏差位置与回归测试结果。
  • 实现“Java(08) - 注解与反射 / @RequestParam vs @RequestBody(前端联调必懂)”的最小代码或配置,检验“这是前后端联调最常见的问题之一。”,输出命令、结果与 Diff,并说明不适用边界。

注解(@xxx)是 Spring 的基础。你在 demo 代码里见过的 @RestController、@Autowired 全是注解。

一、注解是什么?

注解就是代码里的 @xxx 标记。你已经见过一堆了:

@RestController              // 标记:这是个 REST 接口类
@RequestMapping("/organization")  // 标记:处理 /organization 请求
public class OrganizationController {

    @Autowired               // 标记:这个字段要框架注入
    private OrganizationService organizationService;

    @GetMapping("/getById")  // 标记:处理 GET 请求
    public R<OrganizationOut> getOrganization(@RequestParam("id") int id) { ... }
}

注解的本质:给代码"贴标签",标签本身不干活,是框架读取这些标签后决定怎么处理


二、用前端类比理解

注解很像前端的装饰器(decorator),如果你用过 Angular 或 TS 装饰器:

// Angular(概念几乎一样)
@Component({
    selector: 'app-user'
})
export class UserComponent { }

// Vue 装饰器写法
@Component
export default class MyComponent extends Vue { }

或者更通俗的类比:注解像快递单上的标签——"易碎"、"加急"、"冷藏"。包裹本身没变,但快递公司看到标签会用不同方式处理。

@RestController  → 框架看到:哦,这个类要当接口处理
@Autowired       → 框架看到:哦,这个字段我要塞个对象进去
@GetMapping      → 框架看到:哦,这个方法处理 GET 请求

三、demo 常见注解速查

3.1 Spring Web 注解(接口层)

注解 作用 前端类比
@RestController 声明 REST 接口类 Express router
@RequestMapping("/x") 类/方法的路径前缀 app.use('/x')
@GetMapping("/y") 处理 GET 请求 router.get('/y')
@PostMapping("/y") 处理 POST 请求 router.post('/y')
@RequestParam 取 URL 参数 ?id=1 req.query.id
@RequestBody 取请求体 JSON req.body
@PathVariable 取路径参数 /user/{id} req.params.id

3.2 Spring 容器注解(管理对象)

注解 作用
@Service 标记这是个 Service,交给框架管理
@Component 通用组件标记
@Autowired 自动注入依赖
@Repository 标记数据访问层

3.3 其他常见

注解 作用
@Slf4j Lombok:自动生成日志对象 log
@Data Lombok:自动生成 getter/setter
@Transactional 数据库事务(要么全成功要么全回滚)
@Valid / @Validated 参数校验

四、@RequestParam vs @RequestBody(前端联调必懂)

这两个直接关系到你前端怎么传参,重点讲:

4.1 @RequestParam —— 接收 URL 参数

@GetMapping("/getById")
public R<OrganizationOut> getOrganization(@RequestParam("id") int id) { ... }

前端这样调:

axios.get('/organization/getById?id=123')  // 参数在 URL 上

4.2 @RequestBody —— 接收 JSON 请求体

@PostMapping("/listByGroup")
public R<List<OrganizationOut>> listByGroup(@RequestBody OrganizationIn organizationIn) { ... }

前端这样调:

axios.post('/organization/listByGroup', {  // 参数在请求体
    groupId: 1,
    ids: [1, 2, 3]
})

对照:

注解 参数位置 适用 前端写法
@RequestParam URL ?xx=yy 简单参数、GET get('/api?id=1')
@RequestBody 请求体 JSON 复杂对象、POST post('/api', {...})

联调踩坑:如果后端用 @RequestBody,前端却把参数拼在 URL 上,后端收不到(反之亦然)。这是前后端联调最常见的问题之一。


五、Lombok 注解:少写样板代码

demo 大量用 Lombok 自动生成代码。最常见的 @Data

@Data   // ← 这一个注解,自动生成下面所有 getter/setter
public class OrganizationOut {
    private Integer id;
    private String name;
}

// 等价于手写:
// public Integer getId() { return id; }
// public void setId(Integer id) { this.id = id; }
// public String getName() { return name; }
// public void setName(String name) { this.name = name; }
// ... 还有 toString、equals 等

类比:就像 TS 不用手写一堆样板代码。@Data 帮你把 getter/setter 全生成了,所以 demo 的实体类看起来很干净,只有字段。

常见 Lombok 注解:

注解 作用
@Data getter + setter + toString + equals
@Slf4j 生成日志对象 log
@NoArgsConstructor 生成无参构造方法
@AllArgsConstructor 生成全参构造方法
@Builder 生成建造者模式

六、反射:注解能生效的底层原理(了解即可)

反射是 Java 的一种能力:程序运行时,能"反过来"检查和操作类的结构(有哪些字段、方法、注解)。

为什么需要它?因为注解只是"标签",得有人在运行时读取这些标签才能生效。这个读取动作就靠反射:

框架启动时:
1. 反射扫描所有类
2. 发现 @RestController → 注册成接口
3. 发现 @Autowired → 找到对应对象塞进去
4. 发现 @GetMapping("/getById") → 建立 URL 到方法的映射

类比:注解是快递标签,反射是快递员的"识别标签并据此处理"的能力。

你现在不用深究反射的写法,只需理解:

注解(标签)+ 反射(读取标签的能力)= Spring 框架的魔法基础

平时开发几乎不用手写反射,框架都封装好了。


七、本课小结

  • 注解 @xxx = 给代码贴标签,本身不干活,框架读取后决定怎么处理
  • 类比前端的装饰器,或快递单上的"易碎/加急"标签
  • 必记:@RestController/@GetMapping/@RequestParam(URL参数)/@RequestBody(JSON体)
  • @Service/@Autowired 让框架管理和注入对象
  • Lombok@Data/@Slf4j)自动生成样板代码,所以 demo 实体类很干净
  • 反射 = 运行时读取标签的能力,是注解生效的底层原理(了解即可)
  • 阶段二完成!下一阶段:Spring Boot 入门(第 9 课 IoC/DI)

八、总结

  • 注解是什么?:注解就是代码里的 @xxx 标记。
  • 用前端类比理解:注解很像前端的装饰器(decorator),如果你用过 Angular 或 TS 装饰器:
  • demo 常见注解速查:| @Service | 标记这是个 Service,交给框架管理 |
  • @RequestParam vs @RequestBody(前端联调必懂):这是前后端联调最常见的问题之一。
  • Lombok 注解:少写样板代码:@Data 帮你把 getter/setter 全生成了,所以 demo 的实体类看起来很干净,只有字段。
  • 反射:注解能生效的底层原理(了解即可):反射是 Java 的一种能力:程序运行时,能"反过来"检查和操作类的结构(有哪些字段、方法、注解)。

学完自测

选择所有正确答案;提交后逐项核对判断依据。

1在“注解与反射”中,需要同时满足“注解是什么?”与“用前端类比理解”。给定正文约束“给代码"贴标签",标签本身不干活,是框架读取这些标签后决定怎么处理。”,哪些判断保持了原有处理机制?多选
2“注解与反射”出现偏差:“在“注解与反射 / 其他常见”中,即使不满足“自动生成日志对象 log |”,结果与副作用仍会保持不变。”已成为实际行为。围绕“其他常见”与“@RequestParam vs @RequestBody(前端联调必懂)”,哪些判断能定位被改变的职责或边界?多选
3评审“注解与反射”方案时,验收条件包含“如果后端用 @RequestBody,前端却把参数拼在 URL 上,后端收不到(反之亦然)。”。关于“@RequestBody —— 接收 JSON 请求体”与“Lombok 注解:少写样板代码”的哪些决策符合正文机制?多选