写点什么

Lombok 使用引发的血案

作者:技术小生
  • 2022 年 7 月 04 日
  • 本文字数:1334 字

    阅读完需:约 4 分钟

Lombok使用引发的血案

简介

由于 Lombok 注解的便捷性,现在实体类中都是用 Lombok 注解。

其中在实体类中使用的 Lombok 注解主要有以下几种:

@Data

注解在上;提供类所有属性的 get 和 set 方法,此外还提供了 equals、canEqual、hashCode、toString 方法。

@Setter

注解在属性上;为单个属性提供 set 方法; 注解在上,为该类所有的属性提供 set 方法。

@Getter

注解在属性上;为单个属性提供 get 方法; 注解在上,为该类所有的属性提供 get 方法。

@EqualsAndHashCode

注解在上, 可以生成 equals、canEqual、hashCode 方法。

@ToString

这个注解用在上,可以生成所有参数的 toString 方法。


@Data 注解就包含其他注解的功能。一般情况下,直接使用 @Data 实现。


@Builder

使用建造者模式构建实体对象,只能标注到类上,将生成类的一个当前流程的一种链式构造工厂。


@NoArgsConstructor

生成无参构造方法


@AllArgsConstructor

对实体内所有属性生成全部参数的构造方法。如果应用该注解,必须同时使用 NoArgsConstructor 生成无参构造方法。Java 中明确说明,当一个类中没有定义任何构造方法的话,系统默认给该类提供一个无参数的构造方法,这个构造方法被称为缺省构造器。当一个类显示地将构造方法定义出来了,那么系统就不再默认为这个类提供缺省构造器。开发必须手动的为当前类提供无参数构造方法,因为无参数构造方法使用非常普遍。


问题描述

线上问题就是由于对于 Lomkob 注解使用不当造成的。今天系统上线后,发现接口访问经常性超时。排查发现是调用订单中心接口发生异常,该功能就是判断该用户是否存在对应类型的订单。对应的接口请求实体类如下:

@Data@Builder@NoArgsConstructor@AllArgsConstructorpublic class OrderQueryReq {
/** * 用户id */ private Long userId; /** * 每页条数 */ private Integer pageSize = 1;
/** * 课程类型 */ private String courseType;
/** * 订单状态 */ private String status;
/** * 支付时间结束 */ private String payEndTime;}
复制代码

对应的实体类中默认 pageSize 为 1。但是在排查过程中,发现接口交互的请求参数中没有 pageSize 属性。

            PageResp<OrderResp> orderPage = orderCenterAgent.getOrder(OrderQueryReq.builder()                    .userId(userId).payEndTime(DateUtil.timeToString(payTime)).courseType(courseType)                    .status(orderStatus).build());
复制代码

请求构造使用的 Builder 注解提供的建造者构建器。

但是 class 文件反编译出的 Builder 构建器中并没有 pageSize 默认值

所以构造出的对象也就没有 pageSize 参数。


原因分析

业务功能只是判断该用户是否存在对应类型的订单。因没有传 PageSize 参数,查询该用户所有该类型的订单。由于有些用户的订单量较多,所以会在查询过程中出现超时问题。

解决方法

Lombok 在使用 @Builder 时,不会对成员变量设置默认着。可以通过设置 @Builder.Default 注解后,利用标识判断是否启用默认值。

在需要设置默认值的属性字段上,加 @Builder.Default 注解

编译后生成的 Class 如下:

在构建器 build 的时候,会判断是否对存在该注解的字段进行赋值。如果没有,则使用实体对象中对该字段初始的默认值。

接口超时问题得以解决。


用户头像

技术小生

关注

还未添加个人签名 2019.10.08 加入

还未添加个人简介

评论

发布
暂无评论
Lombok使用引发的血案_七月月更_技术小生_InfoQ写作社区