简介
Lombok在java开发者当中作为比较知名的自动代码生成工具,经常用来自动生成set方法、get方法、equals 方法、 hashCode 方法、构造函数方法、log变量生成等。
核心原理是在java编译期间扩展注解处理器:
javax.annotation.processing.AbstractProcessor
自动生成相关代码。
https://github.com/projectlombok/lombok/blob/master/src/core/lombok/core/AnnotationProcessor.java
但是自动生成的逻辑也会让我们在开发中踩坑。
坑:@ToString注解带来的
1、导致StackOverflowError 异常;
像树之类的数据结构:
@ToString
@Setter
@Getter
public static class Node {
private Object vale;
private Node left;
private Node parent;
private Node right;
}
就存在循环引用,最终导致栈溢出异常。
当然你可以使用
@ToString(exclude = "parent")
解决,不过我们必须时刻记着配置,影响我们的开发注意力。
2、在Hibernate 实体中,如果属性带有注解FetchType.LAZY,就会导致懒加载失效,导致性能问题;
坑:使用@AllArgsConstructor,而未使用@NoArgsConstructor
使用了@AllArgsConstructor,就会导致java编译器,不再生成默认构造函数,在一些反序列框架中,如果没有默认构造函数,就会导致反序列化失败。
坑:@EqualsAndHashCode导致Hash容器寻不到数据
默认情况下,非static、非transient 的字段用来参与equals、hashCode方法的实现,对于Hash容器,如果这两个方法的实现随着属性字段的修改,会导致找不到元素值的现象。
示例:
package com.example.demo;
import lombok.*;
import java.util.HashMap;
import java.util.Map;
/**
* @author 认知科技技术团队
* 微信公众号:认知科技技术团队
*/
public class Demo {
public static void main(String[] args) throws ReflectiveOperationException {
Map<Node,Node> map = new HashMap();
Node node = new Node();
node.setVale("who");
map.put(node,node);
Node node1 = map.get(node);
System.out.println(node1);
node.setVale("are");
node1 = map.get(node);
System.out.println(node1);
}
@Setter
@Getter
@EqualsAndHashCode
@ToString
public static class Node {
private Object vale;
}
}
运行结果:
坑:@Setter、@Getter注解导致的序列化坑:第一个字母小写,第二个字母大写的属性生成的get-set方法,与idea,Mybatis,Java官方认可的生成的不一样,导致字段序列化失败
示例:
@Setter
@Getter
@EqualsAndHashCode
@ToString
public static class Node {
private Object nName;
}
看一下生成的字节码反编译的效果:
我们对比下idea,Mybatis,Java官方认可的生成的方法:
Lombok@Setter、@Getter注解对于第一个字母小写,第二个字母大写的属性生成的get-set方法,与idea,Mybatis,Java官方认可的生成的方法是不相同的,主要区别在于第一个字母是小写还是大写。这样就会导致一些序列化问题,比如mybatis框架就不能把此类字段的值序列化到数据库。
小结
Lombok自动生成代码工具虽然避免了冗余和样板代码,让我们的类看着整洁,但是也造成了一些问题,上述只列出了项目中常见的,还有许多坑点,在此不再一一列举。
如果要使用Lombok,我们最好验证一下自动生成的代码(反编译字节码),是不是符合我们的需求。
我们的项目规范:一律禁止使用Lombok工具,使用IDE自动生成。