Java 开发者几乎都用过 Lombok。一个@Data注解,省去了几十行 getter、setter、equals、hashCode、toString;一个@Slf4j,连 Logger 声明都免了。它让代码变得干净利落,开发效率肉眼可见地提升。但我在多个项目中见过 Lombok 引发的“血案”:JPA 实体栈溢出、JSON 序列化字段丢失、线上日志刷爆磁盘。Lombok 确实是一把双刃剑,用对了效率翻倍,用错了就是灾难。
效率翻倍的一面
Lombok 最大的价值是消除样板代码。以@RequiredArgsConstructor为例,它能为所有final字段生成构造器,配合 Spring 的构造器注入,代码从:
@Service public class OrderService { private final OrderRepository orderRepository; private final InventoryClient inventoryClient; public OrderService(OrderRepository orderRepository, InventoryClient inventoryClient) { this.orderRepository = orderRepository; this.inventoryClient = inventoryClient; } }变成:
@Service @RequiredArgsConstructor public class OrderService { private final OrderRepository orderRepository; private final InventoryClient inventoryClient; }字段一旦增减,构造器自动更新,不会漏改。再加上@Builder链式构建、@Slf4j日志注入,编码速度确实能提升一个档次。
灾难的一面:三个典型场景
场景一:@Data用在 JPA 实体上
@Data会生成equals和hashCode,默认使用所有非静态、非瞬态字段。如果两个实体互相引用(比如订单和订单项),hashCode会递归调用,直接栈溢出。更常见的是,JPA 实体通常有自增 ID,在 ID 为 null 时equals比较的是所有字段,两个新建的“空对象”可能被判定相等,放入 Set 后行为诡异。正确做法是:实体类只加@Getter、@Setter,equals和hashCode基于业务主键手动实现,或者用@EqualsAndHashCode(onlyExplicitlyIncluded = true)只包含 ID 字段。
场景二:@Builder与 Jackson 反序列化冲突
@Builder生成的构建器很好用,但它会生成一个全参构造器,同时默认的无参构造器被覆盖。Jackson 反序列化时需要一个无参构造器或@JsonCreator,结果直接报InvalidDefinitionException。解决办法是同时加上@NoArgsConstructor和@AllArgsConstructor,或者用@Jacksonized。但很多人不知道,线上接口突然 500,排查半天才发现是 Lombok 的“锅”。
场景三:@ToString触发懒加载和敏感信息泄露
在 JPA 实体上直接@Data或@ToString,打印日志时如果实体有关联集合且处于懒加载状态,toString会触发额外的 SQL 查询,轻则性能下降,重则LazyInitializationException。更危险的是,用户实体里包含密码、身份证号,@ToString会一股脑打出来,日志文件成了敏感信息泄露的重灾区。正确做法是@ToString(exclude = {"password", "idCard"}),或者干脆不生成 toString。
还有这些隐性成本
Lombok 是编译期注解处理器,代码在 IDE 里看起来正常,但编译后的 class 文件才包含生成的方法。如果团队成员没有安装 Lombok 插件,打开项目就是满屏红。升级 JDK 版本时,Lombok 也可能因为内部 API 变更而失效,导致构建失败。此外,调试时想看某个 getter 的实现,却发现源码里根本不存在,只能反编译 class 文件。
如何用好这把剑
第一,明确使用边界。DTO、VO 可以用@Data,实体类慎用,领域对象只加@Getter。第二,显式控制生成内容。@EqualsAndHashCode只包含业务主键,@ToString排除敏感字段,@Builder配合@NoArgsConstructor和@AllArgsConstructor。第三,团队统一规范。在项目 README 中写明 Lombok 使用约定,CI 中确保编译通过,避免有人本地正常、线上构建失败。第四,不要过度依赖。如果生成逻辑复杂,宁可手写,也不要为了少写几行代码而埋下隐患。
Lombok 本身没有错,错的是不加思考地滥用。它像一把锋利的手术刀,在懂解剖的人手里能精准切除冗余,在不了解结构的人手里则会割伤自己。用之前多问一句:这个注解会生成什么?会不会影响序列化、持久化、日志?想清楚了,它才是真正的效率利器。