1. 简介

Project Lombok 是一个非常流行的 Java 库,它能显著减少我们日常开发中那些重复冗余的样板代码。

在这篇文章中,我们将重点看看 Lombok 的 @Builder 注解是如何工作的,并且深入探讨一下如何根据实际需求对它进行定制化改造。

2. Maven 依赖配置

首先,在你的 pom.xml 中添加 Lombok 依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
</dependency>

3. Lombok 的 @Builder 注解

在讲如何自定义之前,我们先快速回顾一下 Lombok 的 @Builder 注解的基本用法。如果你已经熟悉 Lombok,可以跳过这部分。

@Builder 可以自动生成一个类的 Builder 模式实现
比如我们有一个消息系统,用户之间可以发送文本或文件消息。使用 Lombok,我们可以这样定义 Message 类:

@Builder
@Data
public class Message {
    private String sender;
    private String recipient;
    private String text;
    private File file;
}

其中 @Data 自动生成了 getter、setter、toString、equals 和 hashCode 方法。

使用 Builder 模式构建对象也很简单:

Message message = Message.builder()
  .sender("alice@example.com")
  .recipient("bob@example.com")
  .text("How are you today?")
  .build();

虽然 @Builder 支持默认值等特性,但这里我们不展开。从这个例子可以看出,@Builder 是一个非常强大、能显著减少模板代码的工具。

4. 自定义 Lombok Builder

上面的例子展示了如何使用 Lombok 自动生成 Builder,但在实际开发中,我们可能需要对 Builder 做一些定制。

比如,在我们的 Message 类中,消息内容只能是文本或文件中的一个,不能同时存在。但 Lombok 并不知道这个业务约束,它生成的 Builder 也不会阻止我们同时设置 textfile

⚠️ 这时候就需要我们手动介入,对 Builder 进行定制。

Lombok 提供了一种非常优雅的方式来自定义 Builder:

我们只需要手动编写想要自定义的部分,Lombok 就不会生成那部分代码。

在我们的例子中,我们可以这样写:

public static class MessageBuilder {
    private String text;
    private File file;

    public MessageBuilder text(String text) {
        this.text = text;
        verifyTextOrFile();
        return this;
    }

    public MessageBuilder file(File file) {
        this.file = file;
        verifyTextOrFile();
        return this;
    }

    private void verifyTextOrFile() {
        if (text != null && file != null) {
            throw new IllegalStateException("Cannot send 'text' and 'file'.");
        }
    }
}

注意:我们并没有手动定义 senderrecipient 相关的字段和方法,这些仍然由 Lombok 自动生成。

如果尝试同时设置 textfile

Message message = Message.builder()
  .sender("alice@example.com")
  .recipient("bob@example.com")
  .text("How are you today?")
  .file(new File("/path/to/file"))
  .build();

就会抛出异常:

Exception in thread "main" java.lang.IllegalStateException: Cannot send 'text' and 'file'.

✅ 这样一来,我们就成功地在 Builder 中加入了业务逻辑校验。

5. 总结

这篇文章我们介绍了如何自定义 Lombok 的 Builder,特别是如何在 Builder 中加入业务约束逻辑。

Lombok 的强大之处在于它既提供了默认实现,又保留了足够的扩展空间。通过手动实现部分 Builder 方法,我们可以在不破坏原有便利性的前提下,增强其功能。

一如既往,本文的完整代码可以在 GitHub 仓库 中找到。


原始标题:Lombok Builder with Custom Setter | Baeldung