一、区别体现
首先先看看传统依赖注入和使用@RequiredArgsConstructor的区别:
传统形式:
@Resource
private UserService userService;
@Autowired
private ILockService lockService;
使用@RequiredArgsConstructor:
private final UserService userService;
private final ILockService lockService;
少量的注入可能体现不出明显的区别,但在项目中如果出现类似于下面这种大量注入的话,区别就明显体现出来了:

而使用@RequiredArgsConstructor就明会优雅很多:

简而言之,@RequiredArgsConstructor 是 Lombok 提供的一个非常实用的注解,用于自动生成构造函数。它会为所有 final 字段和标记了@NonNull 的字段生成一个包含这些参数的构造函数。
那么应该如何使用呢?
二、使用注解
示例1:基本使用
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class User {
private final Long id; // final 字段 → 包含在构造函数中
private final String name; // final 字段 → 包含在构造函数中
@NonNull
private String email; // @NonNull 字段 → 包含在构造函数中
private Integer age; // 普通字段 → 不包含在构造函数中
// Lombok 会自动生成:
// public User(Long id, String name, String email) {
// this.id = id;
// this.name = name;
// this.email = email;
// }
}
示例2:实际使用场景
@Service
@RequiredArgsConstructor
public class UserService {
// 依赖注入的 Bean 通常用 final 修饰
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final EmailService emailService;
// 自动生成的构造函数:
// public UserService(UserRepository userRepository,
// PasswordEncoder passwordEncoder,
// EmailService emailService) {
// this.userRepository = userRepository;
// this.passwordEncoder = passwordEncoder;
// this.emailService = emailService;
// }
// 不需要写 @Autowired(Spring 4.3+ 支持构造器注入)
}
三、重要特性详解
1. final 字段
@RequiredArgsConstructor
public class Product {
private final String sku; // 包含
private final BigDecimal price; // 包含
private String description; // 不包含(非final)
}
2. @NonNull 字段
@RequiredArgsConstructor
public class Order {
@NonNull
private Customer customer; // 包含(会生成 null 检查)
@NonNull
private LocalDateTime orderTime; // 包含
private String notes; // 不包含
// 生成的构造函数会包含 null 检查:
// public Order(@NonNull Customer customer,
// @NonNull LocalDateTime orderTime) {
// if (customer == null) throw new NullPointerException("customer is marked non-null but is null");
// if (orderTime == null) throw new NullPointerException("orderTime is marked non-null but is null");
// this.customer = customer;
// this.orderTime = orderTime;
// }
}
四、注意事项
1、继承问题
@RequiredArgsConstructor
public class Parent {
private final String parentField;
}
@RequiredArgsConstructor
public class Child extends Parent {
private final String childField;
// ❌ 错误!需要显式调用父类构造函数
// public Child(String childField) {
// super(???); // 缺少 parentField 参数
// }
}
// 正确做法:
@RequiredArgsConstructor
public class Child extends Parent {
private final String childField;
// 需要手动添加构造函数
public Child(String parentField, String childField) {
super(parentField);
this.childField = childField;
}
}
2、与 @Data 组合使用
@Data
@RequiredArgsConstructor
public class Employee {
private final String employeeId;
@NonNull
private String name;
private String department;
// 会生成:构造函数、getter、setter、equals、hashCode、toString
}
3、序列化兼容性
@RequiredArgsConstructor
public class SerializableData implements Serializable {
private final String data;
private transient String cache; // transient 字段也会包含在构造函数中!
// 生成:public SerializableData(String data, String cache)
}
五、实践建议
1、优先使用 final 字段:确保依赖不可变
2、Spring 项目中推荐使用:减少样板代码
3、配合 @NonNull 使用:增加空安全检查
4、注意字段顺序:构造函数参数顺序与字段声明顺序一致
5、避免过度使用:如果有特殊构造逻辑,还是需要手动写构造函数
小结一下:这个注解还是比较实用的,特别适合Spring 项目中的依赖注入场景,能显著减少样板代码。

979

被折叠的 条评论
为什么被折叠?



