深入解析 Lombok 的实现原理:以 @Builder 为例的实战演示(三)
文章目录
- Lombok 的实现原理概述
- 以 @Builder 为例:解析 Lombok 如何生成 Builder 模式
- 示例代码:没有 Lombok 的 Builder 模式
- 使用 Lombok 的 @Builder 简化代码
- Lombok 如何实现 @Builder:源码解析
- 案例演示:自定义构造逻辑
- Lombok 的代码生成优势
- 总结
- 推荐阅读文章
Lombok 作为 Java 开发中的“魔法工具”,极大简化了样板代码的编写需求,比如
getter/
setter、构造函数、
toString、
equals、
hashCode 以及
Builder 模式等。然而很多人可能好奇,Lombok 是如何实现的?为何我们只需要一个注解,就能自动生成这些代码呢?
本文将通过解析 Lombok 的实现原理,并结合 @Builder 注解的具体示例,带你一步步揭开 Lombok 的神秘面纱。
Lombok 的实现原理概述
Lombok 的核心机制在于注解处理器(Annotation Processor)和抽象语法树(AST)操作。在 Java 编译阶段,Lombok 的注解处理器会捕捉和解析源代码中的注解,然后通过修改 AST(抽象语法树)来添加新的方法、构造器等代码,最终生成编译后的字节码。
-
注解处理器:Lombok 利用 JSR 269 提供的注解处理 API(如
javax.annotation.processing.Processor接口)来捕捉 Java 编译过程中的注解。Lombok 的注解处理器会在编译时扫描项目中的 Lombok 注解(如@Getter、@Setter),然后调用相应的代码生成逻辑。 -
修改 AST:Lombok 利用
Javac或Eclipse等编译器内部 API 直接操作抽象语法树,将新方法或字段等直接插入到 AST 中,实现代码的“动态扩展”。 -
编译输出:经过 Lombok 注解处理的代码在 AST 被修改后会直接编译成字节码,不再额外生成 .java 文件。这就是 Lombok 生成的代码能在编译期生效而不影响源码的原因。
以 @Builder 为例:解析 Lombok 如何生成 Builder 模式
示例代码:没有 Lombok 的 Builder 模式
首先,我们来看一个传统的 Builder 模式实现:
public class User {private String name;private int age;private User(Builder builder) {this.name = builder.name;this.age = builder.age;}public static class Builder {private String name;private int age;public Builder name(String name) {this.name = name;return this;}public Builder age(int age) {this.age = age;return this;}public User build() {return new User(this);}}
}// 使用
User user = new User.Builder().name("Alice").age(25).build();
这种方式虽然有效,但代码略显冗长,特别是当类的字段较多时,Builder 类的代码量将成倍增加。
使用 Lombok 的 @Builder 简化代码
通过 Lombok 的 @Builder 注解,我们可以轻松实现 Builder 模式,大幅减少样板代码:
import lombok.Builder;@Builder
public class User {private String name;private int age;
}// 使用
User user = User.builder().name("Alice").age(25).build();
在此代码中,我们仅需一个 @Builder 注解,Lombok 就能自动生成 Builder 类,并提供链式调用的构建方法。这背后就是 Lombok 操作 AST 的“魔法”。
Lombok 如何实现 @Builder:源码解析
- 注解处理器捕获 @Builder:Lombok 的注解处理器会在编译时扫描
@Builder注解,识别到需要应用 Builder 模式的类。 - AST 操作:Lombok 利用编译器的 AST API,动态插入
UserBuilder类,并为每个字段生成setter方法。最终的代码结构会类似于我们手写的传统 Builder 类。 - 生成静态
builder()方法:在目标类User中插入一个builder()静态方法,用于实例化UserBuilder类。这使得我们可以通过User.builder()调用构建对象。
在编译后的字节码中,Lombok 自动生成的代码结构如下:
public class User {private String name;private int age;public static UserBuilder builder() {return new UserBuilder();}public static class UserBuilder {private String name;private int age;public UserBuilder name(String name) {this.name = name;return this;}public UserBuilder age(int age) {this.age = age;return this;}public User build() {return new User(this.name, this.age);}}
}
Lombok 会自动将这些代码生成并编译为字节码文件,因此我们不需要额外编写 UserBuilder 类。
案例演示:自定义构造逻辑
有时,我们可能希望在构造过程中加入一些自定义逻辑,例如对字段进行校验。让我们看看 Lombok 的 @Builder 如何与自定义构造逻辑结合。
import lombok.Builder;@Builder
public class Product {private String name;private double price;private Product(String name, double price) {if (price < 0) {throw new IllegalArgumentException("Price cannot be negative");}this.name = name;this.price = price;}
}// 使用
Product product = Product.builder().name("Laptop").price(999.99).build();
在此代码中,我们手动定义了 Product 类的构造方法,@Builder 会调用此构造方法,因此在创建 Product 对象时会触发校验逻辑,确保价格不为负数。
Lombok 的代码生成优势
Lombok 的注解处理机制和 AST 操作带来了几个显著优势:
- 减少样板代码:开发者只需声明字段和注解即可,Lombok 会自动生成所有必需的构造方法和构建器方法。
- 可读性提升:通过使用
@Builder等注解,代码逻辑更加简洁和易读。 - 灵活性:Lombok 可以与手写代码兼容,允许在
@Builder模式下添加自定义构造方法,以满足业务需求。 - 编译期生成:Lombok 所有的代码生成操作均在编译期完成,不会影响运行期性能。
总结
Lombok 的 @Builder 是基于注解处理器和 AST 操作的强大工具,极大地简化了 Java 中常见的样板代码,尤其是 Builder 模式的实现。Lombok 不仅支持简单的对象构建,还允许开发者通过自定义构造方法来实现更复杂的初始化逻辑。
Lombok 的底层实现让我们不用关注复杂的 AST 操作,只需简单的注解即可实现强大的构建功能。通过对 @Builder 工作原理的理解,我们可以更深入地掌握 Lombok,并在需要时进行灵活调整。希望本文能帮助你更好地利用 Lombok 的“魔法”简化开发过程!
推荐阅读文章
-
探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)
-
为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)
-
由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)
-
如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系
-
HTTP、HTTPS、Cookie 和 Session 之间的关系
-
什么是 Cookie?简单介绍与使用方法
-
什么是 Session?如何应用?
-
使用 Spring 框架构建 MVC 应用程序:初学者教程
-
有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误
-
把握Java泛型的艺术:协变、逆变与不可变性一网打尽
-
Java Spring 中常用的 @PostConstruct 注解使用总结
-
如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)
-
解密 Redis:如何通过 IO 多路复用征服高并发挑战!
-
线程 vs 虚拟线程:深入理解及区别
-
深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别
-
10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!
相关文章:
深入解析 Lombok 的实现原理:以 @Builder 为例的实战演示(三)
文章目录 Lombok 的实现原理概述以 Builder 为例:解析 Lombok 如何生成 Builder 模式示例代码:没有 Lombok 的 Builder 模式使用 Lombok 的 Builder 简化代码 Lombok 如何实现 Builder:源码解析案例演示:自定义构造逻辑Lombok 的代…...
SEO基础:什么是SERP?【百度SEO专家】
SEO基础:什么是SERP? 大家好,我是林汉文(百度SEO专家),在进行SEO(搜索引擎优化)时,理解SERP是一个非常重要的基础概念。那么,究竟什么是SERP呢?本…...
HTML5教程(一)- 网页与开发工具
1. 什么是网页 网页 基于浏览器阅读的应用程序,是数据(文本、图像、视频、声音、链接等)展示的载体常见的是以 .html 或 .htm 结尾的文件 网站 使用 HTML 等制作的用于展示特定内容相关的网页集合。 2. 网页的组成 浏览器 代替用户向服务…...
Java进阶篇设计模式之二 ----- 工厂模式
前言 在上一篇中我们学习了单例模式,介绍了单例模式创建的几种方法以及最优的方法。本篇则介绍设计模式中的工厂模式,主要分为简单工厂模式、工厂方法和抽象工厂模式。 简单工厂模式 简单工厂模式是属于创建型模式,又叫做静态工厂方法模式。…...
考研篇——数据结构王道3.2.2_队列的顺序实现
目录 1.实现方式说明2.代码实现2.12.1.1 代码12.1.2 代码22.1.3 代码3 2.22.2.1 代码42.2.5 代码52.2.6 代码6 总结 1.实现方式说明 多在选择题中考察 队尾指针(rear)有两种指向方式: 队尾指针指向队尾元素的位置,队尾指针指向…...
从零开始理解 Trie 树:高效字符串存储与查找的利器【自动补全、拼写检查】
题目分析 这道题让我们实现一个 Trie 类(也称为前缀树),以便高效地插入和查询字符串。前缀树是一种特殊的树形数据结构,适用于快速存储和检索字符串数据集中的键,比如实现 自动补全 和 拼写检查。 题目要求 Trie 类…...
关于sse、websocket与流式渲染
一、SSE是什么? 网络中的 SSE (Server-Sent Events) 是一种服务器向浏览器单向推送数据的机制,常用于需要实时更新的数据传输,如新闻推送、股票行情、聊天应用等。 SSE 的特点: 单向通信:服务器向客户端推送数据&…...
Python 语法与数据类型详解
Python 语法与数据类型详解 Python 以其简洁易读的语法和丰富多样的数据类型在编程领域占据重要地位。深入理解 Python 的语法和数据类型是掌握这门语言的关键。 一、Python 语法概述 (一)缩进规则 Python 独特的缩进规则是其语法的重要特征之一。与…...
LeetCode题练习与总结:扁平化嵌套列表迭代器--341
一、题目描述 给你一个嵌套的整数列表 nestedList 。每个元素要么是一个整数,要么是一个列表;该列表的元素也可能是整数或者是其他列表。请你实现一个迭代器将其扁平化,使之能够遍历这个列表中的所有整数。 实现扁平迭代器类 NestedIterato…...
51单片机快速入门之 AD(模数) DA(数模) 转换 2024/10/25
51单片机快速入门之 AD(模数) DA(数模) 转换 2024/10/25 声明:本文图片来源于网络 A模拟信号特点: 电压或者电流 缓慢上升 随着时间连续缓慢上升或下降 D数字信号特点:电压或者电流 保持一段时间的高/低电平 状态 / 突变 (高电压瞬间低电压) 数字电路中 通常将0-1v电压称…...
Typora 、 Minio and PicGo 图床搭建
流程介绍 本地安装Typora笔记工具拥有一台装有docker的服务器配置minio云图床管理控制页面下载PicGo上传工具服务器Docker环境搭建—Ubuntu系统 删除旧docker的所有依赖(非root用户) # 删除docker及安装时自动安装的所有包 sudo apt-get autoremove docker docker-ce docker…...
【计网】UDP Echo Server与Client实战:从零开始构建简单通信回显程序
目录 前言: 1.实现udpserver类 1.1.创建udp socket 套接字 --- 必须要做的 socket()讲解 代码实现:编辑 代码讲解: 1.2.填充sockaddr_in结构 代码实现: 代码解析: 1.3.bind sockfd和…...
微服务网关Zuul
一、Zuul简介 Zuul是Netflix开源的微服务网关,包含对请求的路由和过滤两个主要功能。 1)路由功能:负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础。 2)过滤功能:负责对请求的过程…...
BuildCTF线上赛WP
Build::CTF flag不到啊战队--WP 萌新战队,还请多多指教~ 目录 Build::CTF flag不到啊战队--WP Web ez!http find-the-id Pwn 我要成为沙威玛传奇 Misc what is this? 一念愚即般若绝,一念智即般若生 别真给我开盒了哥 四妹,你听…...
《使用Gin框架构建分布式应用》阅读笔记:p143-p207
《用Gin框架构建分布式应用》学习第10天,p143-p207总结,总计65页。 一、技术总结 1.auth0 本人实际工作中未遇到过,mark一下,参考:https://auth0.com/。 2.使用template (1)c.File() (2)router.Static() (3)rou…...
华为网络管理配置实例
目录 组网需求 数据规划 配置思路 操作步骤 结果验证 配置脚本 管理员可以通过eSight网管系统对FW进行监控和管理,接收FW的告警。 组网需求 如图1所示,某企业在网络边界处部署了FW作为安全网关,并部署了eSight网管系统对网络设备进行集中…...
大语言模型数据处理方法(基于llama模型)
文章目录 前言一、基于huggingface的DataCollatorForSeq2Seq方法解读1、DataCollatorForSeq2Seq方法2、batch最长序列填充3、指定长度填充二、构建大语言模型数据加工模块1、数据读取2、数据加工1、数据格式2、预训练(pretrain)数据加工3、微调(sft)数据加工①、sft数据加工…...
爱奇艺大数据多 AZ 统一调度架构
01# 导语 爱奇艺大数据技术广泛应用于运营决策、用户增长、广告分发、视频推荐、搜索、会员营销等场景,为公司的业务增长和用户体验提供了重要的数据驱动引擎。 多年来,随着公司业务的发展,爱奇艺大数据平台已积累了海量数据,这…...
【C++篇】栈的层叠与队列的流动:在 STL 的韵律中探寻数据结构的优雅之舞
文章目录 C 栈与队列详解:基础与进阶应用前言第一章:栈的介绍与使用1.1 栈的介绍1.2 栈的使用1.2.1 最小栈1.2.2 示例与输出 1.3 栈的模拟实现 第二章:队列的介绍与使用2.1 队列的介绍2.2 队列的使用2.2.1 示例与输出 2.3 队列的模拟实现2.3.…...
使用 Flask 实现简单的登录注册功能
目录 1. 引言 2. 环境准备 3. 数据库设置 4. Flask 应用基本配置 5. 实现用户注册 6. 实现用户登录 7. 路由配置 8. 创建前端页面 9. 结论 1. 引言 在这篇文章中,我们将使用 Flask 框架创建一个简单的登录和注册系统。Flask 是一个轻量级的 Python Web 框架…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...
Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
