Java实际开发@常用注解(附实战场景)

在Java开发的进阶之路上,注解(Annotation)绝对是提升效率的"神器"。它不像业务逻辑那样直观,却悄悄简化了配置、规范了代码、降低了耦合,让我们从繁琐的XML和重复代码中解放出来。

但注解种类繁多,不少初学者会陷入"学了不用就忘"的困境。今天,我们只聚焦实际开发中高频出现的注解,按"Spring核心、Web开发、数据持久层、代码工具、JDK基础"五大场景分类,结合真实业务案例讲透用法,看完直接复制到项目里用!

一、Spring核心注解:控制反转与依赖注入的基石

Spring框架的核心是IOC(控制反转)和AOP(面向切面编程),而注解正是实现这些特性的核心载体,日常开发中几乎每写一个类都可能用到。

1. @Component及其衍生注解:将类交给Spring管理

作用:标记类为"Spring受管Bean",让Spring自动创建实例并放入容器,无需手动new对象。这是依赖注入的前提。

衍生注解(语义更清晰,功能一致):

  • @Controller:用于Controller层(接收请求、返回响应),明确类的职责是处理前端请求。

  • @Service:用于Service层(业务逻辑处理),标识这是核心业务类,便于后续AOP切面增强(如事务、日志)。

  • @Repository:用于Dao层(数据访问),早期配合Spring Data使用,现在更多被MyBatis的@Mapper替代,但语义上仍推荐保留。

实战示例:

java 复制代码
// Controller层:接收用户请求
@Controller
@RequestMapping("/user")
public class UserController {
    // 依赖注入Service层对象
    @Autowired
    private UserService userService;
    
    // 处理查询用户请求
    @GetMapping("/{id}")
    @ResponseBody
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

// Service层:处理业务逻辑
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    
    // 事务注解:保证业务原子性
    @Transactional
    @Override
    public User getUserById(Long id) {
        // 业务逻辑处理
        return userDao.selectById(id);
    }
}

2. @Autowired与@Resource:依赖注入的"双雄"

作用:从Spring容器中获取Bean并注入到当前类中,避免手动调用getBean(),是解耦的关键。

核心区别(开发中必须分清):

  • @Autowired:Spring自带注解,按"类型(byType)"注入,若同类型有多个Bean,需配合@Qualifier指定Bean名称。

  • @Resource:JDK自带注解(javax.annotation.Resource),默认按"名称(byName)"注入,若名称匹配不上则按类型匹配,无需额外注解。

实战避坑:

java 复制代码
@Service
public class OrderService {
    // 场景1:同类型只有一个Bean,直接用@Autowired
    @Autowired
    private OrderDao orderDao;
    
    // 场景2:同类型有多个Bean(如两个PaymentService实现类),需指定名称
    @Autowired
    @Qualifier("alipayService") // 对应Bean的名称(默认类名首字母小写)
    private PaymentService paymentService;
    
    // 场景3:用@Resource更简洁,直接指定名称
    @Resource(name = "wechatPayService")
    private PaymentService wechatPaymentService;
}

3. @Transactional:一行代码搞定事务管理

作用:为方法添加事务支持,保证"要么全成功,要么全失败",是解决数据一致性问题的核心注解(如订单创建+库存扣减必须同时成功)。

关键属性(开发中常用):

  • rollbackFor:指定哪些异常触发回滚(默认只回滚运行时异常),必须配置,否则非运行时异常(如IOException)不会回滚。

  • propagation:事务传播行为,如REQUIRED(默认,当前无事务则新建,有则加入)、REQUIRES_NEW(强制新建事务)。

实战示例:

java 复制代码
@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private StockDao stockDao;
    
    // 核心业务:创建订单+扣减库存,必须原子性
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    @Override
    public void createOrder(Order order) {
        // 1. 创建订单
        orderDao.insert(order);
        // 2. 扣减库存(若此处抛异常,订单创建会回滚)
        stockDao.decreaseStock(order.getProductId(), order.getNum());
    }
}

二、Web开发注解:接口开发的"快捷键"

无论是Spring MVC还是Spring Boot,接口开发都离不开这些注解,它们定义了请求方式、参数映射、响应格式,是前后端交互的桥梁。

1. @RequestMapping及其衍生注解:定位接口地址

作用:映射HTTP请求到Controller的方法上,指定接口的访问路径和请求方式。

衍生注解(替代@RequestMapping,更简洁):

  • @GetMapping:对应GET请求,用于查询数据(如查用户、查订单)。

  • @PostMapping:对应POST请求,用于提交数据(如创建用户、下单)。

  • @PutMapping:对应PUT请求,用于更新数据(全量更新)。

  • @DeleteMapping:对应DELETE请求,用于删除数据。

实战示例:

java 复制代码
@RestController // = @Controller + @ResponseBody,返回JSON格式
@RequestMapping("/product") // 类级别的路径前缀
public class ProductController {
    // 查单个商品:GET /product/1
    @GetMapping("/{id}")
    public Product getProduct(@PathVariable Long id) {
        // 业务逻辑
    }
    
    // 新增商品:POST /product
    @PostMapping
    public Result addProduct(@RequestBody Product product) { // @RequestBody接收JSON参数
        // 业务逻辑
        return Result.success();
    }
    
    // 更新商品:PUT /product/1
    @PutMapping("/{id}")
    public Result updateProduct(@PathVariable Long id, @RequestBody Product product) {
        // 业务逻辑
        return Result.success();
    }
    
    // 删除商品:DELETE /product/1
    @DeleteMapping("/{id}")
    public Result deleteProduct(@PathVariable Long id) {
        // 业务逻辑
        return Result.success();
    }
}

2. 参数映射注解:@PathVariable、@RequestBody、@RequestParam

作用:将HTTP请求中的参数"取"出来,绑定到方法的形参上,是接口接收数据的核心。

  • @PathVariable:获取URL路径中的参数(如/order/{id}中的id),常用于RESTful风格接口。

  • @RequestBody:获取请求体中的JSON数据,用于接收复杂对象(如新增用户时的用户名、密码、手机号等组合参数)。

  • @RequestParam:获取URL查询参数(如/order?status=1&page=1),可指定是否必传、默认值。

实战示例:

java 复制代码
@GetMapping("/order")
// 分页查询订单:/order?status=1&page=1&size=10
public PageInfo<Order> getOrderList(
    @RequestParam(required = true) Integer status, // 必传参数
    @RequestParam(defaultValue = "1") Integer page, // 非必传,默认值1
    @RequestParam(defaultValue = "10") Integer size) { // 非必传,默认值10
    return orderService.getOrderList(status, page, size);
}

三、数据持久层注解:与数据库交互的"简化器"

无论是MyBatis还是Spring Data JPA,这些注解都能替代繁琐的XML配置,让数据库操作更简洁。

1. MyBatis核心注解:@Mapper、@Select、@Insert等

作用:MyBatis的注解式开发,无需写Mapper.xml文件,直接在接口方法上定义SQL。

常用注解:

  • @Mapper:标记Dao接口,让MyBatis扫描并生成代理对象,无需在启动类加@MapperScan。

  • @Select/@Insert/@Update/@Delete:直接在注解中写SQL语句,适用于简单查询。

  • @Param:为方法参数指定别名,便于在SQL中引用(当参数超过1个时必须用)。

实战示例:

java 复制代码
// Dao层接口
@Mapper
public interface UserDao {
    // 简单查询:根据ID查用户
    @Select("SELECT id, username, phone FROM user WHERE id = #{id}")
    User selectById(Long id);
    
    // 多参数查询:根据用户名和手机号查用户
    @Select("SELECT id, username, phone FROM user WHERE username = #{name} AND phone = #{phone}")
    User selectByNameAndPhone(@Param("name") String username, @Param("phone") String phone);
    
    // 新增用户
    @Insert("INSERT INTO user(username, phone, create_time) VALUES(#{username}, #{phone}, NOW())")
    @Options(useGeneratedKeys = true, keyProperty = "id") // 返回自增主键
    void insert(User user);
}
点击并拖拽以移动

2. Spring Data JPA注解:@Entity、@Id、@Column

作用:JPA是ORM框架的规范,通过注解映射Java类与数据库表的关系,实现"零SQL"开发。

核心注解:

  • @Entity:标记类为"实体类",对应数据库中的一张表。

  • @Id:指定类的主键字段,对应表的主键。

  • @GeneratedValue:指定主键生成策略(如自增、UUID)。

  • @Column:指定字段与表列的映射关系(如列名、长度、是否可为空)。

实战示例:

java 复制代码
// 实体类:对应数据库user表
@Entity
@Table(name = "user") // 若类名与表名一致,可省略
public class User {
    // 主键:自增策略
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // 用户名:列名username,非空,长度50
    @Column(name = "username", nullable = false, length = 50)
    private String username;
    
    // 手机号:列名phone,唯一
    @Column(unique = true)
    private String phone;
    
    // 创建时间:列名create_time,自动生成时间
    @Column(name = "create_time")
    private LocalDateTime createTime;
    
    // getter/setter
}
点击并拖拽以移动

四、代码工具注解:提升代码质量的"小助手"

这些注解不涉及业务逻辑,但能规范代码、减少重复代码,是团队开发的"默契"。

1. Lombok注解:消除"样板代码"

作用:Lombok是Java开发的"神器",通过注解自动生成getter/setter、构造方法、toString等重复代码,让类更简洁。

高频注解:

  • @Data:组合注解,包含@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor,开发中最常用。

  • @NoArgsConstructor:生成无参构造方法(JPA必须)。

  • @AllArgsConstructor:生成全参构造方法。

  • @Slf4j:自动生成日志对象log,无需手动声明private static final Logger log = LoggerFactory.getLogger(XXX.class)。

实战示例:

java 复制代码
// 加了Lombok注解后,无需写getter/setter、toString等
@Data
@NoArgsConstructor
@AllArgsConstructor
@Slf4j
public class Order {
    private Long id;
    private String orderNo;
    private Long userId;
    private BigDecimal amount;
    
    public void calculateAmount() {
        // 直接使用log对象打印日志
        log.info("订单{}开始计算金额", orderNo);
        // 业务逻辑
    }
}
点击并拖拽以移动

2. 校验注解:@NotNull、@NotBlank、@Valid

作用:参数校验(如前端传的用户名不能为空、手机号格式正确),替代手动if-else判断,提升代码可读性。

常用注解(javax.validation.constraints包):

  • @NotBlank:字符串不为空且不能全是空格(适用于用户名、密码)。

  • @NotNull:对象不为null(适用于数字类型,如age、id)。

  • @Pattern:字符串匹配正则表达式(如手机号、邮箱)。

  • @Valid:触发参数校验,放在方法参数前。

实战示例:

java 复制代码
// 接收前端参数的DTO类
@Data
public class UserDTO {
    @NotBlank(message = "用户名不能为空")
    private String username;
    
    @NotBlank(message = "密码不能为空")
    @Size(min = 6, max = 20, message = "密码长度必须在6-20之间")
    private String password;
    
    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
    private String phone;
    
    @NotNull(message = "年龄不能为空")
    @Min(value = 1, message = "年龄不能小于1")
    private Integer age;
}

// Controller层:触发校验
@PostMapping("/user")
public Result addUser(@Valid @RequestBody UserDTO userDTO, BindingResult bindingResult) {
    // 校验失败,返回错误信息
    if (bindingResult.hasErrors()) {
        String errorMsg = bindingResult.getFieldError().getDefaultMessage();
        return Result.fail(errorMsg);
    }
    // 校验通过,执行业务逻辑
    userService.addUser(userDTO);
    return Result.success();
}

五、JDK基础注解:Java原生的"小工具"

这些是Java自带的注解,虽然简单,但在开发中频繁出现,尤其是代码维护和序列化场景。

  • @Override:标记方法重写了父类的方法,若方法名写错(如把toString写成toStr),编译器会报错,避免低级错误。

  • @Deprecated:标记方法或类已过时,提醒开发者不要使用,同时可通过@deprecated文档注释说明替代方案。

  • @SuppressWarnings:抑制编译器警告(如"未使用的变量""unchecked"警告),谨慎使用,避免掩盖真正的问题。

实战示例:

java 复制代码
public class StringUtils {
    // 重写父类方法,加@Override确保正确性
    @Override
    public String toString() {
        return "StringUtils工具类";
    }
    
    // 标记方法已过时,推荐用newFormat方法
    @Deprecated
    public static String format(String str) {
        return str;
    }
    
    // 新的格式化方法
    public static String newFormat(String str) {
        // 优化后的逻辑
        return "[" + str + "]";
    }
    
    // 抑制unchecked警告(如使用ArrayList未指定泛型时)
    @SuppressWarnings("unchecked")
    public static List getList() {
        return new ArrayList();
    }
}

六、总结:注解的核心价值

这些注解之所以在开发中"高频",本质是因为它们解决了实际问题:

  1. 简化配置:替代XML,让配置信息贴近代码(如@Service、@Entity)。

  2. 解耦代码:通过依赖注入(@Autowired)减少类之间的直接依赖。

  3. 规范行为:通过事务(@Transactional)、校验(@Valid)等注解统一业务规则。

  4. 提升效率:Lombok注解消除样板代码,让开发者聚焦核心业务。

最后提醒:注解不是越多越好,选择"合适的场景用合适的注解"才是关键。收藏这篇文章,开发时遇到注解困惑直接对照,效率翻倍!

相关推荐
老华带你飞2 小时前
在线教育|基于springboot + vue在线教育系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·后端
路边草随风2 小时前
java操作cosn使用
java·大数据·hadoop
码事漫谈2 小时前
VS Code终端从入门到精通完全指南
前端·后端
码事漫谈2 小时前
现代C++系统编程中类型重解释的内存安全范式
后端
TT哇2 小时前
【项目】玄策五子——匹配模块
java·spring boot·websocket·spring·java-ee·maven
JSON_L2 小时前
Fastadmin后台增加切换语言
后端·php·fastadmin
认真敲代码的小火龙2 小时前
【JAVA项目】基于JAVA的医院管理系统
java·开发语言·课程设计
Predestination王瀞潞2 小时前
Java EE开发技术 (报错解决 兼容问题 及 Jakara EE Web 官方手册提供的API接口聚合包)
java·java-ee·jstl·jakara背景
断剑zou天涯2 小时前
【算法笔记】Manacher算法
java·笔记·算法