【Spring】Lombok

Lombok

Quick Start Example for Lombok

在日常开发中,总会写大量的 POJO (如 MessageInfoUserOrder),而这些类几乎都要写 getter、setter、toStringequalshashCode 代码量不小,逻辑却千篇一律,纯属体力活。

Lombok 的出现正是为了终结这种冗余。它通过一组简单的注解,在编译期自动生成那些样板方法,让源码只保留核心的字段声明,清晰且高效。

java 复制代码
import lombok.Data;

@Data
public class MessageInfo {
    private String from;
    private String to;
    private String message;
}

仅此几行,一个功能完备的 POJO 就完成了。

引入依赖与 IDE 配置

使用 Lombok 前需要先将依赖引入项目,并确保开发环境正确识别。

Maven

xml 复制代码
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
</dependency>

Gradle

groovy 复制代码
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'

小贴士:依赖引入后,务必在 IDE 中安装 Lombok 插件 (如 IntelliJ IDEA 的 Lombok 插件),并开启 Enable annotation processing,否则 IDE 会误报找不到方法。对于 Maven/Gradle 编译,开启注解处理器即可。

核心注解详解

Lombok 提供了一系列注解,组合使用可以应对绝大多数场景。其中最核心、最常用的是 @Data

@Data

@Data 是一个组合注解,把它加在类上,相当于同时应用了以下五个注解:

注解 作用
@Getter 为所有字段生成 getter 方法
@Setter 为所有非 final 字段生成 setter 方法
@ToString 生成包含所有字段的 toString() 方法
@EqualsAndHashCode 生成基于所有非静态非瞬态字段的 equals(Object)hashCode() 方法
@RequiredArgsConstructor final 字段或有 @NonNull 约束的字段生成构造器(若没有这类字段,则生成一个公开的无参构造器)

对于最初的 MessageInfo,编译后等价于手写了如下代码:

java 复制代码
public class MessageInfo {
    private String from;
    private String to;
    private String message;

    public MessageInfo() {}

    public String getFrom() { return from; }
    public void setFrom(String from) { this.from = from; }
    public String getTo() { return to; }
    public void setTo(String to) { this.to = to; }
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }

    @Override
    public String toString() { ... }
    @Override
    public boolean equals(Object o) { ... }
    @Override
    public int hashCode() { ... }
}

用类图直观展示 @DataMessageInfo 自动添加的公开方法:
MessageInfo
-String from
-String to
-String message
+MessageInfo()
+getFrom() : String
+setFrom(String from) : void
+getTo() : String
+setTo(String to) : void
+getMessage() : String
+setMessage(String message) : void
+toString() : String
+equals(Object o) : boolean
+hashCode() : int

所有方法均已存在,可直接使用:

java 复制代码
MessageInfo msg = new MessageInfo();
msg.setFrom("Alice");
msg.setTo("Bob");
msg.setMessage("Hello Lombok!");

System.out.println(msg.getFrom());  // Alice
System.out.println(msg);            // MessageInfo(from=Alice, to=Bob, message=Hello Lombok!)

可将原来的列表结构拆分为独立的小章节,每个注解一节,内容适当扩写,示例如下(直接替换原 ### 3.2 其他宝藏注解 整节即可):

已将"注解可作用于类或字段"这一重要说明补充到了文章中,主要在 @Getter 和 @Setter 小节展开,并略微提及了其他注解的类似特性。以下是更新后的 3.2 其他宝藏注解 完整内容:

@Getter 和 @Setter

可作用在字段 上,单独控制读写方法的生成。放在类上,会为所有字段生成 getter/setter;放在单个字段上,则只针对该字段生成。还支持通过 AccessLevel 设置访问级别。

java 复制代码
public class User {
    @Getter @Setter
    private String name;          // 仅为 name 生成

    @Setter(AccessLevel.PROTECTED)
    private String password;      // 生成 protected setter
}

类似地,像 @ToString.Exclude@EqualsAndHashCode.Exclude 这样的辅助注解也可以直接标在字段上,用来精准排除某些字段,而不必在类注解里用字符串指定字段名。

@ToString

生成 toString() 方法。可通过 exclude 排除敏感字段,或用 of 指定仅包含某些字段。也可以直接在字段上添加 @ToString.Exclude 达到相同目的。

java 复制代码
@ToString(exclude = "password")
public class User {
    private String name;
    @ToString.Exclude
    private String password;
}

@EqualsAndHashCode

控制参与相等性比较的字段,同样支持 excludeof,也支持在字段上使用 @EqualsAndHashCode.Exclude。在继承关系 中,务必设置 callSuper = true 来调用父类的实现,避免破坏对称性。

java 复制代码
@EqualsAndHashCode(callSuper = true)
public class Employee extends Person {
    private String empId;
}

@Builder

为类生成建造者模式,优雅构造复杂对象,尤其适用于多参数且部分可选的场景。

java 复制代码
@Builder
public class Order {
    private String id;
    private String customer;
    private BigDecimal amount;
}

// 使用
Order order = Order.builder()
        .id("1001")
        .customer("Alice")
        .amount(new BigDecimal("99.99"))
        .build();

@AllArgsConstructor 和 @NoArgsConstructor

分别生成全参构造器无参构造器 。常与 @Data 搭配,满足序列化框架(如 Jackson)对无参构造器的需求。

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private String name;
    private int age;
}

@Value

不可变数据类的一站式注解,相当于 @Data 的不可变版本。所有字段默认 private final,只会生成 getter,不会生成 setter ,同时生成 toStringequalshashCode。适合定义值对象。

java 复制代码
@Value
public class Address {
    String city;
    String street;
}

@Slf4j / @Log / @Log4j2

直接在类中注入日志对象,省去冗长的声明代码,支持主流日志框架。

java 复制代码
@Slf4j
public class SomeService {
    public void doSomething() {
        log.info("doing something...");
    }
}

@With

为字段生成 withXxx 方法,返回一个修改了指定字段值的新对象,原对象保持不变,非常适合配合不可变对象使用。

java 复制代码
@With
@Value
public class Point {
    int x, y;
}

Point p = new Point(1, 2);
Point p2 = p.withX(10);  // p2: (10,2),p 不变

原理浅析

Lombok 并非运行时动态代理,而是在 Java 编译过程 中对抽象语法树(AST)动手脚。它的工作流程如下:
.java 源文件
编译器 javac 解析
生成抽象语法树 AST
Lombok

注解处理器
识别 @Data 等注解
在 AST 中注入

getter/setter 等方法节点
编译器基于修改后的 AST

生成 .class 字节码
JVM 运行

具体而言,Lombok 利用了 Java 6 引入的 JSR 269 可插拔注解处理 API ,直接参与 javac 的编译过程。在生成 AST 之后、产出字节码之前,Lombok 的处理器会扫描 AST,找到带有自身注解的节点,然后动态插入相应的方法节点。整个过程发生在编译期,对运行时零侵入,也不会带来任何性能损耗。最终生成的 .class 文件与手写完全一致。

相关推荐
小明同学0110 小时前
C++后端项目:统一大模型接入 SDK(五)
服务器·c++·后端·计算机网络·语言模型
SimonKing10 小时前
IP定位库的完美替代品:ip2region,开源、免费!
java·后端·程序员
凤山老林10 小时前
AI辅助编程:Copilot在Java开发中的最佳实践
java·人工智能·copilot
ew4521810 小时前
【Java】Apache POI 终极封装:支持多表格循环、图片插入、日期格式化的Word导出工具类(兼容POI3.17+)
java·word·apache
铁打的阿秀10 小时前
IDEA启动项目报错: 加载主类 com.seeburger.webedi.system.SystemApplication 时出现 LinkageError
java·ide·intellij-idea
ZC跨境爬虫10 小时前
模块化烹饪小程序开发日记 Day5:(后端Flask接口开发与AI智能解析菜谱的实现)
前端·人工智能·后端·python·ui·flask
Yeats_Liao10 小时前
物联网接入层技术剖析(一):从select到epoll
java·linux·后端·物联网·struts
上弦月-编程10 小时前
Java类与对象:编程核心解密
java·开发语言·jvm
小钻风336610 小时前
Spring Boot WebSocket 两种集成方式深度解析
spring boot·后端·websocket