为什么不推荐使用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不好用,它也有它的优点)

相关推荐
码上一元2 小时前
SpringBoot自动装配原理解析
java·spring boot·后端
枫叶_v4 小时前
【SpringBoot】22 Txt、Csv文件的读取和写入
java·spring boot·后端
杜杜的man5 小时前
【go从零单排】Closing Channels通道关闭、Range over Channels
开发语言·后端·golang
java小吕布5 小时前
Java中Properties的使用详解
java·开发语言·后端
2401_857610036 小时前
Spring Boot框架:电商系统的技术优势
java·spring boot·后端
杨哥带你写代码8 小时前
网上商城系统:Spring Boot框架的实现
java·spring boot·后端
camellias_8 小时前
SpringBoot(二十一)SpringBoot自定义CURL请求类
java·spring boot·后端
背水9 小时前
初识Spring
java·后端·spring
晴天飛 雪9 小时前
Spring Boot MySQL 分库分表
spring boot·后端·mysql
weixin_537590459 小时前
《Spring boot从入门到实战》第七章习题答案
数据库·spring boot·后端