Lombok 拾遗
Created|Updated|Java
|Word Count:43|Reading Time:1mins|Post Views:
sneakyThrow
1 | |
Author: magicliang
Copyright Notice: All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.
Related Articles
2026-10-04
Java常用类库-E08-MapStruct与Lombok的生成代码契约
删除手写代码之前先保留行为契约 商品输入对象需要转换成展示对象,还需要支持更新已有对象。MapStruct 可以生成字段映射,Lombok 可以生成访问器、builder 和相等方法。代码行数减少之后,null、集合引用和 hashCode 行为仍然存在;如果不检查生成结果,就可能把原本看得见的决策变成构建过程中隐含的默认值。 本篇使用独立 Maven 模块,实际运行 MapStruct 1.6.3 与 Lombok 1.18.42,并显式加入 lombok-mapstruct-binding 0.2.0。固定源码分别为 b4e25e49deae707b50ce061172e114292b414a23 与 2031eb0880942b5f0b7281580f6e877a3e87279a。所有应用源码保持 Java 8,在 JDK 8 和 JDK 21 分别 clean verify,没有用已经生成的 class 代替处理器执行。 完整项目见 下载处理器实验工程,测试见 ProcessorContractTest.java,生成映射见 ProductMapperImpl.java,...
2026-09-30
深入 OpenTelemetry 25:为自己的库编写 Java Agent 扩展
库没有现成的自动插桩时,业务代码可以显式创建 Span;如果不便改业务代码,也可以让 Agent 扩展匹配库的方法。困难不在调用 spanBuilder,而在确定扩展何时被找到、增强了哪个版本、辅助类由哪个加载器提供,以及异常或禁用时是否留下重复或未结束的 Span。 本文固定 JDK 21.0.12、Java Agent 1.31.0。发行 Agent 的 SHA-256 是 e866de5fa4e4c2c7d076072798fb9ca65b679d9c6be7792b37d4c94e2bc686f7。扩展的编译 API 是 io.opentelemetry.javaagent:opentelemetry-javaagent-extension-api:1.31.0-alpha(SHA-256 afc55fe952fa10fbad2836993bacc2a01cf02e1d50d53a6db9595fb97b2a37aa),Byte Buddy 编译依赖版本与 SHA-256 见 writing-plans/opentelemetry-java/VERSIONS.md;扩展 ...

2026-10-04
设计模式 15:阅读模式先看变化
小额收据原先只显示在屏幕或邮件里,现在审计系统需要 audit/200 的格式。旧方法用渠道名分支,对 audit 抛错。把分支拆成三个类就能叫“策略模式”吗?仅看类图答不了这个问题:先问是谁选择格式、什么行为保持不变、下一次变化要修改哪里。 先补缺失的行为 Before.receipt(200, "audit") 的断言是抛 IllegalArgumentException,刻意保留旧功能缺口。最小修复可以在原 switch 中加一支:Alternative 这样做,还加上负金额拒绝,并保留未知渠道报错。如果渠道是封闭的小集合,需求只来自一个调用位置,这就是合理的实现;没有理由为展示 GoF 模式专门建类层次。 若渠道格式来自调用者的配置,After 接收一个 IntFunction<String>: 123After screen = new After(cents -> "paid " + cents);After audit = new After(cents -> "audit/" + ...
2026-10-03
函数式编程 00:导读与能力自测
两件商品单价 12.50 元,另一件单价 3.20 元,九折后的应付金额是 25.38 元。计算这个数只需要一个循环。程序扩大后,报价还会受日期、规则版本、外部查询和订单状态影响;字段可能非法,文件可能读取失败,任务可能取消。函数式编程的学习路线从这些具体差异出发:计算怎样保持可预测,输入和状态怎样进入类型,计算之间怎样组合,实际执行由谁管理。 认识纯函数、一等函数、部分应用、柯里化和 memoize,已经掌握了函数式编程的重要基础。这些知识主要解释函数怎样作为值使用,以及调用怎样组织。后续还需要不可变数据与别名、求值策略、代数数据类型、错误模型、组合定律和效果生命周期。Monad 位于组合这一段,不能用“还差 Monad 一个术语”衡量整条路线的完成度。 系列共有 40 篇主线和 8 篇选修。主线前半用 Java 21 建立可运行的例子,第 14 篇补足后续需要的 Scala 3 语法,再研究类型构造器与效果组合。选修讨论 λ 演算、参数性、Optics、程序解释和语言生态,按需求进入,不是理解 Optional 的前置门槛。 先定义能观察的行为 教学案例只处理本地合成订单,不...

2026-10-04
设计模式 27:谁能读取延迟加载的库存
库存查询的构建成本较高;访客又不允许查询。旧对象一创建就调用加载器,随后查询时才核对身份,结果是未授权请求已经触发了一次昂贵加载。能否做到先拒绝、授权后首次使用才加载,并让后续查询复用已加载对象? 控制访问与加载时机 Before 在构造器里调用 loader.get();反例断言访客随后被拒绝,加载次数却已经是 1。After 实现与真实 Inventory 相同的 available(sku) 接口,在构造时绑定本章教学角色。调用入口先检查是否为 stock-reader,然后首次使用加载对象、再次使用复用;测试分别断言未授权 0 次加载、授权两次读取只加载 1 次、加载器的异常向外传播。Alternative 用一个普通函数先查角色再加载,适用于只查一次、无需复用实例的场合。 12345public int available(String sku) { authorize(role); if (loaded == null) loaded = loader.get(); return loaded.available(sku);} 此...

2026-10-04
设计模式 E02:record、sealed 类型与模式匹配
第 37 篇用 Visitor 处理“节点类型稳定、操作会增加”的场景。Java 21 的 record、sealed 和 switch 模式匹配把这类模型的另一种写法放进语言里:节点可以是数据载体,类型集合可以被封闭,switch 可以在编译期检查是否覆盖所有已知类型。 record 和 sealed 改变的是数据边界 Oracle JDK 21 文档说明,record 会为组件生成字段、访问器、规范构造器、equals、hashCode 和 toString;record 字段是 final,适合作为简单数据载体。sealed class/interface 则限制哪些类可以继承或实现它。labs/E02 里,Line 只允许 Product 和 Bundle 两种实现,Product 校验 SKU 和金额,Bundle 保存子节点副本。 12345678910111213141516public sealed interface Line permits Product, Bundle { <R> R accept(Visitor<R>...
Contents
