注解完全详解(Lombok 核心注解)
@Builder
Lombok 工具提供的核心注解,用于自动生成「建造者模式」代码,简化对象创建逻辑,提升代码的可读性与维护性。它并非 Spring 框架中的注解,而是与
@Data、@Getter 等同属于 Lombok 生态体系的一部分,专注于减少样板代码。
一、核心基础
1. 归属与依赖
所属工具:Lombok(一款在编译期生成代码的辅助工具)
注解全类名:
lombok.Builder(注意:该注解不属于 Spring 包路径,Spring 的注解通常位于 org.springframework 下)
依赖要求:使用前必须在项目中引入 Lombok 的依赖配置(Maven 或 Gradle),否则注解将不会生效:
<!-- Maven 依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <!-- 建议使用稳定版本 --> <scope>provided</scope> <!-- 仅在编译阶段有效,不打包进最终 Jar 文件 --> </dependency>
IDE 支持:需要在 IDEA 或 Eclipse 中安装 Lombok 插件,否则编辑器可能报红或提示语法错误,但不影响实际编译运行。
2. 核心作用
@Builder 注解会自动为类生成实现「建造者模式」所需的一系列结构,包括:
- 一个名为
XXXBuilder的静态内部类(如
所示,例如XXXBuilder
);UserBuilder - 在 Builder 类中为每个属性生成链式 setter 方法(如
);username(String username) - 在实体类中添加静态的
builder()方法(即
),用于获取 Builder 实例;builder() - Builder 类中提供
build()方法(对应
),用于最终构建并返回实体对象。build()
简而言之:通过链式调用方式替代传统繁琐的构造函数或逐个 set 属性的方式,使对象创建更清晰、灵活。
二、基本用法
1. 单个类上的直接应用
只需在目标实体类上添加 @Builder 注解即可启用建造者模式功能:
import lombok.Builder;
import lombok.Data;
// 结合 @Data 自动生成 getter/setter/toString 等方法
@Data
@Builder
public class User {
private String username; // 用户名(必填)
private Integer age; // 年龄(可选)
private String address; // 地址(可选)
private String email; // 邮箱(可选)
}
@Builder
2. 创建对象示例
无需手动编写任何 Builder 相关代码,直接利用链式语法创建实例:
// 使用建造者模式构建对象(支持任意属性顺序)
User user = User.builder()
.username("zhangsan") // 必填项
.age(25) // 可选项(按需设置)
.address("北京市朝阳区")
.email("zhangsan@xxx.com")
.build(); // 最终生成 User 对象
// 输出结果:User(username=zhangsan, age=25, address=北京市朝阳区, email=zhangsan@xxx.com)
System.out.println(user);
3. 与传统方式对比
| 方式 | 代码示例 | 优点 | 缺点 |
|---|---|---|---|
| 构造方法 | |
写法简洁 | 参数顺序固定,易错;可选参数需大量重载 |
| setter 方法 | |
设置顺序自由 | 代码冗长,容易遗漏字段赋值 |
| 建造者模式 | |
支持链式调用、顺序自由、语义清晰、可读性强 | 需引入 Lombok 依赖 |
三、高级特性
1. 为属性设置默认值
若希望某些可选字段具有默认值,可在定义属性时直接赋予初始值:
@Data
@Builder
public class User {
private String username;
private Integer age = 18; // 默认年龄设为 18
private String address = "未知地址"; // 默认地址
private String email;
}
在使用 builder 构建对象时,未显式设置的属性将自动采用默认值:
User user = User.builder()
.username("lisi")
.email("lisi@xxx.com")
.build();
// 输出:User(username=lisi, age=18, address=未知地址, email=lisi@xxx.com)
System.out.println(user);
2. 必选属性强制校验
@Builder 注解本身并不提供对“必填字段”的强制检查机制。如需实现此类校验逻辑,可通过以下方式补充:
@Builder3. 与其他 Lombok 注解的组合使用
在实际开发中,@Builder 常与多个 Lombok 注解结合使用,以满足更广泛的使用场景。常见的组合如下:
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
@Data // 自动生成 getter、setter、toString、equals 和 hashCode 方法
@Builder // 启用建造者模式,支持链式调用创建对象
@NoArgsConstructor // 生成无参构造函数(便于 Spring 反射或 JSON 反序列化)
@AllArgsConstructor // 生成全参构造函数(Builder 内部依赖此构造函数)
public class User {
private String username;
private Integer age;
private String address;
}
组合使用说明:
@NoArgsConstructor
添加 @NoArgsConstructor 可解决 Spring 容器注入或 JSON 反序列化过程中因缺少无参构造函数而导致的问题;
@AllArgsConstructor
@AllArgsConstructor 是 @Builder 底层实现所依赖的关键注解。虽然 Lombok 在使用 @Builder 时会自动补全全参构造函数,但显式声明更为安全,可避免潜在的注解冲突或行为不一致。
@Builder
4. 控制部分属性不参与建造者构建
若某些字段不应由外部通过 Builder 设置(例如数据库自增的 ID),可通过设置访问级别限制来实现。推荐方式是使用 @Setter(AccessLevel.NONE),从而优雅地排除特定字段:
import lombok.Builder;
import lombok.Data;
import lombok.Setter;
import lombok.AccessLevel;
@Data
@Builder
public class User {
private String username;
private Integer age;
@Setter(AccessLevel.NONE) // 禁止生成 setter 方法,且不加入 Builder 构建流程
private Long id; // 自增主键,由数据库维护,禁止手动赋值
}
此时尝试通过 Builder 设置 id 将导致编译错误:
User user = User.builder()
.username("wangwu")
.age(30)
// .id(1001) // 编译失败:Builder 中不存在该方法
.build();
id
5. 自定义静态建造者入口方法名称
默认情况下,获取 Builder 实例的方法名为 builder(),但可通过 builderMethodName 属性进行自定义命名,提升语义清晰度:
@Data
@Builder(builderMethodName = "create") // 将建造者入口方法改为 create()
public class User {
private String username;
private Integer age;
}
调用时使用新定义的方法名启动构建流程:
User user = User.create() // 替代原有的 User.builder()
.username("zhaoliu")
.age(28)
.build();
XXX.builder()
@Builder(builderMethodName = "create")
四、常见问题与避坑指南
1. 是否与 @ConfigurationProperties 存在冲突?
不存在冲突。@ConfigurationProperties 是 Spring Boot 提供的用于绑定配置文件属性的注解,运行时由 Spring 处理;而 @Builder 是 Lombok 在编译期生成代码的工具,两者作用阶段不同,互不影响,可以共存:
import lombok.Builder;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "user")
@Data
@Builder
public class User {
private String username;
private Integer age;
private String address;
}
@ConfigurationProperties
@Builder
注解配合实现非空校验:通过 @NonNull 强制要求必须设置某些关键属性,否则在运行时抛出空指针异常:
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
@Data
@Builder
public class User {
@NonNull // 必须传入 username,否则运行时报错
private String username;
private Integer age;
private String address;
}
错误示例(未设置必填项):
// 编译通过,但运行时抛出异常:java.lang.NullPointerException: username is marked non-null but is null
User user = User.builder().age(20).build();
@NonNull
NullPointerException
username
局部属性排除方案补充:除 @Setter(AccessLevel.NONE) 外,也可使用 @Builder.Exclude 显式指定某字段不参与构建过程,但目前支持有限且需注意版本兼容性,因此更推荐上述 setter 控制方式。
@Builder.Default
transient
@Setter(AccessLevel.NONE)
@ConfigurationProperties(prefix = "sky.jwt")
@Data
@Builder
public class JwtProperties {
private String adminSecretKey;
private long adminTtl;
private String adminTokenName;
}
在使用 Lombok 的建造者模式时,若实体类存在继承关系,直接使用 @Builder 注解会导致父类的属性无法被 Builder 设置。此时应采用 @SuperBuilder 注解,该功能自 Lombok 1.18.16 版本起支持。
@Builder
首先,父类需标注 @SuperBuilder:
import lombok.Data;
import lombok.SuperBuilder;
@Data
@SuperBuilder
public class BaseEntity {
private Long id;
private String createTime;
}
子类同样使用 @SuperBuilder,可自动继承父类的所有属性:
@Data
@SuperBuilder
public class User extends BaseEntity {
private String username;
private Integer age;
}
构建对象时,可通过 superBuilder() 方法链式设置包括父类在内的全部属性:
User user = User.superBuilder()
.id(1001)
.createTime("2025-11-18")
.username("zhangsan")
.age(25)
.build();
@SuperBuilder
当实体类包含集合类型字段时,若直接初始化赋值,例如:
private List<String> tags = new ArrayList<>();
会导致所有实例共享同一个集合引用,引发“静态共享”问题。正确做法是使用 @Builder.Default 注解,确保每个对象拥有独立的集合实例。
@Builder.Default
示例如下:
import lombok.Builder;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
@Data
@Builder
public class User {
private String username;
// 错误方式:所有对象共享同一 list 实例
// private List<String> tags = new ArrayList<>();
// 正确方式:每个对象创建独立 list
@Builder.Default
private List<String> tags = new ArrayList<>();
}
若编译过程中出现“找不到符号:方法 builder()”错误,可能由以下原因导致:
- 原因一:项目未引入 Lombok 依赖,或当前版本过低不支持相关特性;
- 原因二:开发环境中(如 IDEA)未安装 Lombok 插件,导致编辑器无法识别生成的方法,尽管实际编译可通过;
- 原因三:类中手动定义了与 Builder 冲突的方法,例如已存在名为 builder() 的静态工厂方法或其他构造逻辑。
builder()
适用场景与不适用场景
适用场景:
- 实体类属性较多,尤其存在大量可选字段时,Builder 模式能显著提升对象构建的清晰度和灵活性;
- 追求代码可读性,希望明确展示每个属性的赋值过程;
- 项目中已集成 Lombok(如配合 @Data、@AllArgsConstructor 等注解使用),无需额外引入新工具库。
@Data
不适用场景:
- 简单 POJO 类(仅包含 2-3 个属性),此时直接调用构造函数或 setter 更加直观简洁;
- 需要创建不可变对象(immutable object),建议结合
final关键字与 @Singular 或手动实现 Builder,而非依赖默认 @Builder 行为;
final
@AllArgsConstructor
@Builder 是 Lombok 提供的核心注解,并非 Spring 框架的一部分,其主要作用是自动生成符合建造者模式的构建代码。
@Builder
其核心优势包括:
- 支持链式调用,语法流畅;
- 属性设置顺序自由,无需遵循参数列表顺序;
- 减少模板代码,提升可读性和维护性。
常见高效组合为:@Data + @Builder,适用于绝大多数复杂实体类的构建需求。
@Data + @Builder + @NoArgsConstructor + @AllArgsConstructor
使用过程中需注意避坑要点:
- 集合类型的默认值必须配合 @Builder.Default 使用,避免实例间状态污染;
- 涉及继承结构时,应使用 @SuperBuilder 而非 @Builder;
- @Builder 与 Spring 相关注解(如 @ConfigurationProperties、@Component)完全兼容,无冲突风险。
@Builder.Default
@SuperBuilder

雷达卡


京公网安备 11010802022788号







