为什么不推荐使用Lombok?@Data不香吗?


一、前言

之前写项目遇到的一个Bug,下面是模拟代码。

新建一个springboot的项目,Person一个实体类,定义一个方法传一个JSON数据

typescript 复制代码
@Data
public class Person {
    private String name;
    private String aName;
    private String aaName;
}
less 复制代码
@SpringBootApplication
@RestController
public class LombokTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(LombokTestApplication.class, args);
    }

    @PostMapping("/user")
    public String userSearch(@RequestBody Person person){
        System.out.println(person);
        return "okk~";
    }

}

springboot启动之后postman发送一次请求。

请求路径:http://localhost:8080/user

JSON数据:

json 复制代码
{
    "name": "aaa",
    "aName": "bbb",
    "aaName": "ccc"
}

后台输出结果

编辑

我们会发现,aName字段为null?居然接收不了,而aaName可以接受,这是为什么呢?

二、源码跟踪

分析这个源码要对SpringMVC框架有一定的理解,它的最基础的请求处理也是基于原生的servlet去进行了一个扩展,它扩展的一个核心叫做 DispatcherServlet ,它的所有的http请求都会去走 doDispatch 这个方法。

编辑

在大概540行左右的handle,这里在调用,我们关注的是 为什么那个aName参数它没有解析出来,后面执行会调用 InvocableHandlerMethod 里面的 getMethodArgumentValues 方法。

编辑

在方法的return部分我们打了个断点,看看会返回啥?

编辑

发现这个方法返回就使aName变成了null(这里就已经完成了参数解析了,说明问题出在这一块)。

然后进过一系列的操作,我们最终来到了 POJOPropertiesCollector 的 collectAll 这个方法,我们在 _addFields 与 _addMethods 打个断点。

编辑

跑一下,在_addFields他的size为0,我们再来看看_addMethods,它的size为3。

编辑

我们点击下一步(不是下一个断点)发现他的长度变成了4了,而且还多了个aname的字段

编辑

按住ctrl键点击_addMethods我们进去看看,这个方法填加了一个字段。

ini 复制代码
protected void _addMethods(Map<String, POJOPropertyBuilder> props) {
        Iterator var2 = this._classDef.memberMethods().iterator();

        while(var2.hasNext()) {
            AnnotatedMethod m = (AnnotatedMethod)var2.next();
            int argCount = m.getParameterCount();
            if (argCount == 0) {
                this._addGetterMethod(props, m, this._annotationIntrospector);
            } else if (argCount == 1) {
                this._addSetterMethod(props, m, this._annotationIntrospector);
            } else if (argCount == 2 && Boolean.TRUE.equals(this._annotationIntrospector.hasAnySetter(m))) {
                if (this._anySetters == null) {
                    this._anySetters = new LinkedList();
                }

                this._anySetters.add(m);
            }
        }

    }

我们再点击下一步,一直到_removeUnwantedAccessor这个,发现size变成3了,这里就删除了我们的aName字段,保留了aname,这就是问题的关键了。

编辑

这里我们要看看这个@Data到底生成了什么东西,我们在终端敲入命令:mvn clean package

编辑

我们看看反编译出来的到底是个啥?

编辑

左边是手动生成的get set 方法,右边是@Data 生成的,我们发现了自己生成的 getaName 它的a是小写的,而@Data生成的getAName的A是大写的。

编辑

而getAName可能反推出aName和aname两个可能,所以在_removeUnwantedAccessor这里就删除了aName这个字段,就后台接受不到了。

三、总结

这个bug虽然不算什么,但是这也是个细节,虽然像aName这种不规范的命名字段很少用,但是这里模拟当初项目的出错,这里还是建议大家使用手动或者快捷键生成的实体类的方法(当然不是Lombok不好用,它也有它的优点)

相关推荐
RANCE_atttackkk12 分钟前
Springboot+langchain4j的RAG检索增强生成
java·开发语言·spring boot·后端·spring·ai·ai编程
好好研究2 小时前
Spring Boot - Thymeleaf模板引擎
java·spring boot·后端·thymeleaf
爬山算法2 小时前
Hibernate(76)如何在混合持久化环境中使用Hibernate?
java·后端·hibernate
她说..2 小时前
策略模式+工厂模式实现单接口适配多审核节点
java·spring boot·后端·spring·简单工厂模式·策略模式
csdn_aspnet2 小时前
ASP.NET 8 - Cookie 身份验证
后端·asp.net·cookie·.net8
笔画人生2 小时前
Cursor + 蓝耘API:用自然语言完成全栈项目开发
前端·后端
有来技术3 小时前
ASP.NET Core 权限管理系统(RBAC)设计与实现|vue3-element-admin .NET 后端
vue.js·后端·c#·asp.net·.net
qq_12498707533 小时前
基于springboot的林业资源管理系统设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
shuair4 小时前
springboot整合redisson单机模式
java·spring boot·后端
qq_12498707534 小时前
基于springboot的竞赛团队组建与管理系统的设计与实现(源码+论文+部署+安装)
java·vue.js·spring boot·后端·信息可视化·毕业设计·计算机毕业设计