Spring Boot Common Annotations
注解是 Spring Boot 与开发者之间的接口语言:声明组件、绑定请求、注入配置、划定事务边界,全部通过注解表达。本文按功能域整理实际开发中的高频注解,每个注解只保留最简示例与选型决策。启动与自动装配机制见 Spring Boot Startup,Bean 定义与注入方式对比见 Spring Boot Bean 使用规范。
Bean 定义与注入
组件注解均派生自 @Component,差异只在语义分层:
| 注解 | 语义 | 场景 |
|---|---|---|
@Component | 通用组件 | 不属于下列分层的组件 |
@Service | 业务逻辑 | Service 层 |
@Repository | 数据访问 | 持久化层,附加异常转换 |
@Controller / @RestController | Web 入口 | 视图渲染 / REST API |
@Configuration | 配置声明 | 内含 @Bean 方法 |
第三方类无法添加注解,用 @Bean 声明:
1 | |
注入注解的选择:
| 注解 | 匹配方式 | 说明 |
|---|---|---|
@Autowired | 先类型后名称 | 单构造器可省略 |
@Qualifier | 显式限定 | 多实现时指定 Bean 名称 |
@Primary | 标记首选 | 多实现中的默认候选 |
@Resource | 先名称后类型 | JSR-250 标准 |
决策:依赖注入一律构造器注入加 final 字段;多实现用 @Qualifier 显式指定,不依赖字段名巧合匹配;@Autowired 与 @Resource 不混用,团队统一一种。三种注入方式的完整对比见 Bean 使用规范一文。
生命周期回调用 @PostConstruct / @PreDestroy,比实现 InitializingBean / DisposableBean 接口侵入性更低:
1 | |
Web 层注解
@RestController
@Controller + @ResponseBody 的组合:方法返回值直接序列化为响应体,不走视图解析。REST API 一律用它;需要渲染模板(Thymeleaf 等)才用 @Controller。
请求映射
1 | |
路径设计约束:资源用名词复数,动作用 HTTP 方法表达;创建返回 201,删除返回 204。@RequestMapping 的 consumers / produces 限定媒体类型;跨域单点控制用 @CrossOrigin,全局则走配置。
参数绑定
| 注解 | 数据来源 | 典型场景 |
|---|---|---|
@PathVariable | URL 路径模板变量 | GET /users/{id} |
@RequestParam | 查询参数 / 表单字段 | ?page=0&size=20 |
@RequestHeader | 请求头 | Authorization |
@CookieValue | Cookie | 会话标识 |
@RequestBody | 请求体 | JSON 反序列化到 record |
@RequestPart | multipart 部分 | 文件上传 |
@ModelAttribute | 查询参数绑定到对象 | 列表筛选条件 |
1 | |
@RequestBody 每个方法最多一个(请求体流只读一次);参数名与变量名不一致时用 name 属性显式指定。
参数校验
入口校验用 @Valid 触发 Bean Validation,DTO 用 record 承载:
1 | |
1 | |
校验失败抛出 MethodArgumentNotValidException,由全局处理器统一转 400,Controller 不做 try-catch。
全局异常处理
@RestControllerAdvice + @ExceptionHandler 把领域异常映射为 HTTP 响应:
1 | |
一个应用一个 @RestControllerAdvice;兜底的 Exception 处理器不回传堆栈与内部细节,只记日志。
一个请求经过的注解
配置注入注解
@Value
1 | |
支持默认值(: 后缀)与 SpEL(#{} 表达式)。只适合零散标量。
@ConfigurationProperties
相关配置项成组绑定为不可变对象,record 的构造器绑定天然契合:
1 | |
1 | |
注册方式二选一:配置类上 @EnableConfigurationProperties(MailProperties.class),或主类标注 @ConfigurationPropertiesScan。引入 spring-boot-configuration-processor 后 IDE 可补全并校验属性名。
| 维度 | @Value | @ConfigurationProperties |
|---|---|---|
| 粒度 | 单个属性 | 一组属性 |
| 松散绑定 | 不支持 | kebab-case 自动映射驼峰 |
| 校验 | 不支持 | 类上 @Validated 启用 |
| IDE 元数据 | 无 | 配置处理器生成 |
决策:一个前缀下超过两个属性就改用 @ConfigurationProperties。
@Profile 与 @PropertySource
@Profile 按 spring.profiles.active 激活对应组件:
1 | |
@PropertySource 引入额外 properties 文件;实践中分环境更常用 application-{profile}.yml,前者多用于装载第三方配置文件。
数据访问注解
实体映射
1 | |
三条硬规则:
- 关联一律 LAZY,EAGER 会在列表查询中放大成 N+1
@CreatedDate/@LastModifiedDate必须配@EntityListeners与@EnableJpaAuditing,缺失时字段静默为 null- Entity 用普通类而非 record,JPA 需要无参构造与可变状态
@Repository
标记持久化层,并把底层异常翻译为 DataAccessException 层次。接口继承 JpaRepository 即获得 CRUD 与分页:
1 | |
@Transactional
事务边界放在 Service:
1 | |
readOnly = true 让 Hibernate 跳过脏检查,列表查询明显受益。
四个常见失效或错用场景:
- 自调用:同类方法内部调用不经过代理,注解失效
- 非 public 方法上的注解不生效(代理机制限制)
- 异常被方法内 try-catch 吞掉,事务照常提交
- 默认只回滚
RuntimeException与Error,受检异常需rollbackFor = Exception.class显式声明
@EntityGraph 与 @Modifying
1 | |
@EntityGraph 一次 JOIN 预取关联,消除 N+1(列表场景优先考虑 DTO 投影);@Modifying 标记 UPDATE / DELETE 的 JPQL,必须在事务内调用,返回受影响行数。
条件装配注解
自动配置的基石,日常开发多用于 starter 与内部组件库:
| 注解 | 生效条件 |
|---|---|
@ConditionalOnClass | 类路径存在指定类 |
@ConditionalOnMissingClass | 类路径不存在指定类 |
@ConditionalOnBean | 容器中存在指定 Bean |
@ConditionalOnMissingBean | 容器中不存在指定 Bean |
@ConditionalOnProperty | 属性匹配期望值 |
1 | |
条件评估的时机与 @Conditional 元注解机制见 Startup 一文的自动配置章节。用户定义的 Bean 永远优先于自动配置(@ConditionalOnMissingBean),这也是覆盖框架默认组件的标准姿势。
任务执行注解
@Scheduled
1 | |
启用需 @EnableScheduling。注意三点:
- 默认调度线程池只有 1 个线程,一个任务阻塞会顺延全部任务,多任务场景配置
spring.task.scheduling.pool.size - cron 表达式 6 位(秒 分 时 日 月 周),与 Linux crontab 的 5 位不同
fixedDelay是上次结束到下次开始,fixedRate是固定频率,语义不同
@Async
1 | |
启用需 @EnableAsync。两个前提:不能自调用,方法需 public。void 方法的异常进入 AsyncUncaughtExceptionHandler,调用方不可见–需要感知结果或失败时,返回 CompletableFuture。
校验注解速查
Bean Validation(Jakarta Validation)常用约束:
| 注解 | 语义 | 适用类型 |
|---|---|---|
@NotNull | 不为 null | 任意 |
@NotBlank | 去除空白后非空 | String |
@NotEmpty | 非 null 且非空 | String / 集合 |
@Size(min, max) | 长度或元素数 | String / 集合 |
@Min / @Max | 数值下限 / 上限 | 数字 |
@Email | 邮箱格式 | String |
@Pattern(regexp) | 正则匹配 | String |
@Past / @Future | 必须在过去 / 未来 | 时间类型 |
@Valid 与 @Validated 的分工:@Valid 加在参数上触发对象校验与嵌套级联;@Validated 加在类上启用方法级参数校验,覆盖 @RequestParam、@PathVariable 这类标量参数。
1 | |
方法级校验失败抛出 ConstraintViolationException,同样交给全局处理器转 400。
速查总表
| 分类 | 注解 |
|---|---|
| 启动 | @SpringBootApplication |
| Bean 定义 | @Component / @Service / @Repository / @Configuration / @Bean |
| 依赖注入 | @Autowired / @Qualifier / @Primary / @Resource |
| Web | @RestController / @RequestMapping 族 / @PathVariable / @RequestParam / @RequestBody |
| 校验 | @Valid / @Validated / Bean Validation 约束 |
| 配置 | @Value / @ConfigurationProperties / @Profile |
| 数据访问 | @Entity / @Repository / @Transactional / @EntityGraph |
| 条件装配 | @ConditionalOnClass / @ConditionalOnProperty / @ConditionalOnMissingBean |
| 任务 | @Scheduled / @Async |
注解背后是同一条主线:声明元数据交给框架,框架在运行期通过代理、后置处理器、条件评估补全装配逻辑。理解每个注解触发的机制,比记住语法更能避免"注解不生效"这类问题。



