核心注解速查
本教程共 48 篇 · 第 9 篇 · 更新于 2026-08-13 · 约 4 分钟阅读
本节目标:把最常用的 Spring / Spring Boot 注解集中过一遍——含义、用法、常见坑,当字典查。
注解是贴在代码上的「元数据」:不改逻辑,只加说明。Spring 读注解来决定行为。前 8 章零散出现过不少,这章按用途归类,做速查。
组件与配置
| 注解 | 作用 | 章节 |
|---|---|---|
@SpringBootApplication | 主类三合一:自动配置 + 组件扫描 + 配置 | 4、6 |
@Component / @Service / @Repository / @Controller | 声明 Bean | 7 |
@Configuration | 配置类,里面放 @Bean 方法 | 7 |
@Bean | 手动声明一个 Bean | 7 |
Web 注解:写接口的三件套
@RestController 是 @Controller + @ResponseBody 的合体。返回的对象直接序列化成 JSON 写进响应体,不经过视图解析。写 REST 接口,控制器一律用它。用 @Controller 也能配 @ResponseBody 返回 JSON,但多写一个注解,没必要。
先定义一个数据类,后面例子都用它:
package com.example.demo;
public record User(Long id, String name) {
}
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
// 根据 id 查用户
return new User(id, "码上学");
}
}
@RequestMapping 是通用映射,能配路径和方法。标在类上,给整个控制器加路径前缀;标在方法上,指定具体接口。它有五个快捷注解,日常优先用快捷版:
| 快捷注解 | 等价写法 | 用途 |
|---|---|---|
@GetMapping | @RequestMapping(method = RequestMethod.GET) | 查询 |
@PostMapping | @RequestMapping(method = RequestMethod.POST) | 新增 |
@PutMapping | @RequestMapping(method = RequestMethod.PUT) | 整体更新 |
@PatchMapping | @RequestMapping(method = RequestMethod.PATCH) | 局部更新 |
@DeleteMapping | @RequestMapping(method = RequestMethod.DELETE) | 删除 |
参数绑定注解,一个接口全用上:
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class UserController {
// GET /api/users?page=1&size=20
@GetMapping("/api/users")
public List<User> list(@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int size) {
return List.of();
}
// GET /api/users/42
@GetMapping("/api/users/{id}")
public User get(@PathVariable Long id) {
return new User(id, "码上学");
}
// POST /api/users,body 是 JSON
@PostMapping("/api/users")
public User create(@RequestBody User user) {
return user;
}
}
对照表:
| 注解 | 绑定的数据 | 例子 |
|---|---|---|
@PathVariable | URL 路径变量 | /users/{id} 里的 id |
@RequestParam | 查询参数 / 表单字段 | ?page=1 里的 page |
@RequestBody | 请求体 JSON,自动反序列化 | POST 的 body |
@ModelAttribute | 表单绑定到对象 | 传统 MVC 表单提交 |
Tip
@RequestParam配defaultValue是常见写法。参数可缺省,接口更稳。它默认必填,required = false也能放宽,但通常用defaultValue就够了。
装配注解:依赖怎么进来
@Autowired 按类型自动注入。字段、setter、构造器都能标:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
}
第 7 章说过:单构造器不用标 @Autowired,多构造器才需要它指定「用哪个」。字段注入能写但别写——测试难、依赖不可见。
同类型多个 Bean 时,@Autowired 会迷茫,报 NoUniqueBeanDefinitionException。两个注解救场。
@Qualifier 点名要哪个:
package com.example.demo;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
private final MessageService messageService;
public OrderService(@Qualifier("smsMessageService") MessageService messageService) {
this.messageService = messageService;
}
}
@Primary 指定默认人选——不点名时优先用它:
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class MessageConfig {
@Bean
@Primary
public MessageService emailMessageService() {
return new EmailMessageService();
}
@Bean
public MessageService smsMessageService() {
return new SmsMessageService();
}
}
Tip面试高频:
@Autowired默认按类型装配;类型有多个,按名字找;再不行,配合@Qualifier或@Primary。
配置值:@Value
@Value 把配置值注入字段。带默认值的写法,属性缺失不报错:
package com.example.demo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class MessageService {
@Value("${app.message:默认消息}")
private String message;
public String getMessage() {
return message;
}
}
app.message 在 application.yml 里配:
app:
message: "你好,Spring Boot"
@Value 的值里还能写 SpEL 表达式,比如 @Value("#{systemProperties['user.name']}") 取系统属性。项目里用得少,知道有这回事就行。
Note
@Value适合单个零散值。多个相关属性(一组配置)用@ConfigurationProperties更合适,第 11 章细讲。两者不是替代关系,各有场景。
其他高频注解
| 注解 | 作用 |
|---|---|
@Scope("prototype") | 改 Bean 作用域,默认单例 |
@Lazy | 懒加载,首次使用时才创建 Bean |
@Transactional | 方法 / 类开启事务,异常自动回滚(第 26 章展开) |
@Import | 手动导入其他配置类 |
@Profile | 指定 Profile 下才生效(第 13 章展开) |
@EnableCaching / @EnableAsync | 开启缓存 / 异步支持 |
@ResponseStatus 指定返回的 HTTP 状态码,标在异常类上最常用:
package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
}
控制器里 throw new UserNotFoundException(),响应就是 404,不用写 catch。
@ComponentScan 默认扫主类所在包。需要扩大范围时,用 basePackages 指定额外包:
@ComponentScan(basePackages = {"com.example.demo", "com.example.common"})
一般用不上——主类放顶层包,默认扫描就够。
三个常见坑
注解加错位置。 @Bean 只能放在 @Configuration 类的方法上;@GetMapping 只对控制器方法有意义。注解不是贴纸,位置错了 Spring 不认。
包扫描不到。 Bean 类不在主类所在包的子包里,注入时报 NoSuchBeanDefinitionException。先查包结构,再看扫描范围。
同名 Bean 冲突。 两个 @Bean 方法返回同类型,注入时容器不知道选谁。用 @Primary 定默认、@Qualifier 点名,或者去掉多余那个。
小结
- 写接口:
@RestController+ 方法级快捷映射 + 参数绑定三件套。 - 注入依赖:构造器注入为主,
@Qualifier/@Primary解决多 Bean 冲突。 - 读配置:单值用
@Value,一组用@ConfigurationProperties。 - 其他注解按需查表,用到再深挖。