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

相关推荐
3学习分享吧几秒前
C++从0实现百万并发Reactor服务器(完结)
后端
lssjzmn18 分钟前
java中,synchronized 关键字与 ReentrantLock 重入锁的区别以及应用场景,注意事项
java·后端
南雨北斗26 分钟前
词性
后端
南雨北斗28 分钟前
动词的类型
后端
小厂永远得不到的男人31 分钟前
ioc 原理篇
java·后端
南雨北斗1 小时前
英语音标
后端
ClouGence1 小时前
三步搞定!GaussDB 实时数据入仓
数据库·后端
whitepure1 小时前
万字详解Java枚举
java·后端
用户8356290780511 小时前
在 Java 中读取 Excel 文件
java·后端
canonical_entropy1 小时前
让演化可编程:XLang 与可逆计算的结构化范式
后端