Java 常用注解扩展对比
对比了 Java 开发中常用的各类注解,涵盖 Spring MVC 控制器、Lombok 数据类、MyBatis-Plus 表映射、依赖注入、参数绑定、JPA 实体映射、配置管理、事务管理及测试注解等场景。重点分析了@Controller 与@RestController、@Data 与手动编写、@TableName 规则、@Autowired 与@Resource 等核心区别,并提供了代码示例与最佳实践建议,帮助开发者规范注解使用,提升代码质量与团队协作效率。

对比了 Java 开发中常用的各类注解,涵盖 Spring MVC 控制器、Lombok 数据类、MyBatis-Plus 表映射、依赖注入、参数绑定、JPA 实体映射、配置管理、事务管理及测试注解等场景。重点分析了@Controller 与@RestController、@Data 与手动编写、@TableName 规则、@Autowired 与@Resource 等核心区别,并提供了代码示例与最佳实践建议,帮助开发者规范注解使用,提升代码质量与团队协作效率。


微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
| 对比维度 | @Controller | @RestController |
|---|---|---|
| 定义 | Spring MVC 的基础控制器注解 | @Controller + @ResponseBody 的组合注解 |
| 返回值处理 | 返回视图名称(需配合视图解析器) | 直接返回 JSON/XML 数据(自动添加 @ResponseBody) |
| 适用场景 | 传统 MVC 架构(如 JSP/Thymeleaf 页面渲染) | RESTful API 开发(前后端分离场景) |
| HTTP 响应头 | Content-Type: text/html(默认) | Content-Type: application/json(默认) |
@Controller
public class WebCtrl {
@GetMapping("/page")
public String page() {
return "index"; // 返回视图名
}
}
@RestController
public class ApiCtrl {
@GetMapping("/data")
public User data() {
return userService.findUser(); // 自动转 JSON
}
}
| 对比维度 | 使用 @Data | 不使用 @Data |
|---|---|---|
| 代码量 | 自动生成以下方法:\n- 所有字段的 getter/setter\n- toString()\n- equals()/hashCode() | 需手动编写所有方法 |
| 维护性 | 字段增减时无需修改方法 | 字段变更需同步修改相关方法 |
| 继承关系处理 | 需显式添加 @EqualsAndHashCode(callSuper=true) 包含父类字段 | 手动编写时可直接控制是否包含父类字段 |
| 框架兼容性 | 依赖 Lombok 插件(需 IDE 支持) | 无额外依赖 |
@Data
public class User {
private Long id;
private String name;
// 自动生成所有方法
}
public class ManualUser {
private Long id;
private String name;
// 手动编写 getter/setter
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
}
注意事项:
@Data 时,若类有继承关系,需添加 @EqualsAndHashCode(callSuper=true)@NoArgsConstructor)| 对比维度 | 使用 @TableName | 不使用 @TableName |
|---|---|---|
| 表名映射规则 | 显式指定数据库表名(如 @TableName("sys_user")) | 按 MyBatis-Plus 默认规则映射:\n类名驼峰转下划线(如 SysUser → sys_user) |
| 适用场景 | 1. 表名含特殊字符(如 user-info)\n2. 类名与表名无对应关系 | 类名与表名严格遵循驼峰转下划线规则 |
| 全局配置覆盖 | 优先级高于全局配置 | 可通过配置文件统一设置表名前缀:\nmybatis-plus.global-config.db-config.table-prefix=sys_ |
@Data
@TableName("sys_user") // 显式指定表名
public class User {
private Long id;
}
@Data
public class SysUser { // 默认映射为 sys_user
private Long id;
}
注意事项:
@TableName("order")TableNameHandler)实现| 注解对 | 核心区别 | 使用场景 |
|---|---|---|
| @Autowired vs @Resource | - @Autowired(Spring)按类型注入\n- @Resource(JSR-250)按名称注入 | 明确指定 Bean 名称时用 @Resource,优先使用构造器注入时用 @Autowired |
| @Primary vs @Qualifier | - @Primary标记首选 Bean\n- @Qualifier指定具体 Bean 名称 | 存在多个相同类型 Bean 时,优先使用 @Primary,需精确控制时用 @Qualifier |
代码示例:
// @Autowired + @Qualifier
@Autowired
@Qualifier("mysqlDataSource")
private DataSource dataSource;
// @Resource
@Resource(name = "oracleDataSource")
private DataSource dataSource;
| 注解对 | 核心区别 | 使用场景 |
|---|---|---|
| @RequestParam vs @PathVariable | - @RequestParam获取 URL 参数\n- @PathVariable获取 URI 模板变量 | RESTful 风格 URL 用 @PathVariable,传统表单参数用 @RequestParam |
| @ModelAttribute vs @RequestBody | - @ModelAttribute绑定 Form 表单数据\n- @RequestBody绑定 JSON 请求体 | 表单提交用 @ModelAttribute,API 接口传输复杂对象用 @RequestBody |
代码示例:
// PathVariable
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
...
}
// RequestBody
@PostMapping("/users")
public ResponseEntity<?> createUser(@RequestBody UserDTO userDTO) {
...
}
| 注解对 | 核心区别 | 使用场景 |
|---|---|---|
| @Entity vs @Table | - @Entity声明 JPA 实体类\n- @Table指定数据库表名 | 类名与表名不一致时使用 @Table |
| @Column vs @Transient | - @Column映射数据库列\n- @Transient标记非持久化字段 | 字段需要特殊列名或类型时用 @Column,临时计算字段用 @Transient |
| @OneToMany vs @ManyToOne | - 定义一对多/多对一关系 | 根据业务关系方向选择(部门 - 员工:部门用 @OneToMany,员工用 @ManyToOne) |
代码示例:
@Entity
@Table(name = "departments")
public class Department {
@OneToMany(mappedBy = "department")
private List<Employee> employees;
}
@Entity
public class Employee {
@ManyToOne
@JoinColumn(name = "dept_id")
private Department department;
}
| 注解对 | 核心区别 | 使用场景 |
|---|---|---|
| @Value vs @ConfigurationProperties | - @Value注入单个属性\n- @ConfigurationProperties批量绑定属性 | 简单配置用 @Value,复杂配置对象用 @ConfigurationProperties |
| @Profile vs @Conditional | - @Profile按环境激活配置\n- @Conditional按条件创建 Bean | 多环境配置用 @Profile,动态装配逻辑用 @Conditional |
配置示例:
app:
security:
enabled: true
timeout: 300
代码实现:
@Configuration
@ConfigurationProperties(prefix = "app.security")
public class SecurityConfig {
private boolean enabled;
private int timeout;
// getters/setters
}
| 注解对 | 核心区别 | 使用场景 |
|---|---|---|
| @Data vs @Value | - @Data生成可变对象\n- @Value生成不可变对象(final 字段) | 需要修改字段值时用 @Data,只读数据传输对象用 @Value |
| @Builder vs @AllArgsConstructor | - @Builder支持链式构建\n- @AllArgsConstructor生成全参构造器 | 复杂对象构建用 @Builder,依赖注入全参构造用 @AllArgsConstructor |
代码示例:
@Value
@Builder
public class ImmutablePoint {
private final int x;
private final int y;
}
// 使用 ImmutablePoint point = ImmutablePoint.builder().x(10).y(20).build();
| 注解对 | 核心区别 | 使用场景 |
|---|---|---|
| @Transactional vs @Modifying | - @Transactional声明事务边界\n- @Modifying标记 DML 操作 | 服务层方法用 @Transactional,JPA 更新查询用 @Modifying |
代码示例:
@Service
public class UserService {
@Transactional
public void updateUser(User user) {
userRepository.save(user);
}
}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Modifying
@Query("UPDATE User u SET u.name = ?1 WHERE u.id = ?2")
int updateNameById(String name, Long id);
}
| 注解对 | 核心区别 | 使用场景 |
|---|---|---|
| @Mock vs @MockBean | - @Mock(Mockito)创建模拟对象\n- @MockBean(Spring Boot Test)替换 Spring 容器中的 Bean | 单元测试用 @Mock,集成测试用 @MockBean |
| @SpringBootTest vs @WebMvcTest | - @SpringBootTest加载完整上下文\n- @WebMvcTest仅加载 Web 层组件 | 全集成测试用 @SpringBootTest,控制层隔离测试用 @WebMvcTest |
测试示例:
// 全集成测试
@SpringBootTest
class UserServiceIntegrationTest {
@Autowired
private UserService userService;
}
// 控制层测试
@WebMvcTest(UserController.class)
class UserControllerTest {
@MockBean
private UserService userService;
@Autowired
private MockMvc mockMvc;
}
| 功能场景 | 推荐注解组合 | 典型应用 |
|---|---|---|
| REST API 开发 | @RestController + @RequestBody + @Valid | 前后端分离接口开发 |
| JPA 实体映射 | @Entity + @Table + @Column + @OneToMany | 数据库表结构映射 |
| 配置管理 | @ConfigurationProperties + @Profile | 多环境配置切换 |
| 测试覆盖 | @SpringBootTest + @MockBean + @DataJpaTest(按需选择) | 分层测试策略 |
| 依赖注入 | 构造器注入优先,@Autowired + @Qualifier | 避免循环依赖 |
@RestController代替 @Controller+@ResponseBody)@Component和 @Service)@Data + @Builder@AllArgsConstructor@Transactional(readOnly = true)@Transactional(rollbackFor = Exception.class)@WebMvcTest或 @DataJpaTest通过系统化的注解对比与组合使用,可显著提高代码规范性和团队协作效率。建议结合 SonarLint 等代码质量管理工具,确保注解使用的合理性与一致性。