内容概要
Lombok简介
lombok
是一个实用的第三方java工具,可以通过简单注解来精简代码达到消除冗长代码的目的。有了lombok
后就可以不用写一些繁琐的代码比如getter和setter方法等,通过添加简单的注解,lombok
就能够在编译源码的时候自动帮我们生成这些方法。
官网:https://projectlombok.org/
github地址:https://github.com/rzwitserloot/lombok
lombok优点
Lombok原理
流程图
有了Lombok程序后,javac
编译源码的具体流程:
- 首先javac会对源代码
(Source File)
进行语法分析(Parse)
,生成一棵抽象语法树(AST)
- 在运行过程中调用了实现了
JSR269 API
规范的Lombok程序,接下来进入Annotation Processing
-
Lombok Annotation Processor
就对生成的抽象语法树进行处理,处理过程:例如我们有一个data注解,当我们声明一个变量之后,该注解可以自动生成getter和setter方法,Lombok Annotation Handler
就负责找到注解所在的类对应的语法树,然后修改该语法树,最终输出一个修改过的语法树(Modified AST)
,对于data注解它会在里面增加了getter和setter方法定义的相应树节点 - 拿到修改过的抽象语法树后,javac对它进行解析和生成
(Analyze and Generate)
,最终生成了字节码文件(Byte Code)
Lombok集成
引入Lombok的maven依赖,可以在官网菜单Install-->maven
中找到
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
引入依赖后,必须在IDE上安装lombok插件,否则IDE会报错
IDEA安装Lombok插件
选择菜单File-->Settings-->Plugins --> browser repositories,在新窗口中搜索Lombok plugin
,点击Install
,安装完成之后重启IDEA即可。
Eclipse安装Lombok插件
- 在官网的download菜单里下载
lombok.jar
- 双击运行
lombok.jar
,点击Install
按钮进行安装
- 打开Eclipse,选择菜单Help-->About Eclipse,会显示lombok的版本
如果mac/linux安装不上(权限导致),可以进入lombok下载目录,执行sudo java -jar lombok.jar
,然后安装程序重新启动,进行安装
反编译工具
反编译也就是说将编译好的字节码文件反编译成java源代码,使用的工具是Java Decompiler
。它提供了JD-GUI
图形化工具以及JD-Eclipse
、JD-IntelliJ
插件,我们使用JD-GUI
即可。
官网:http://jd.benow.ca/
JD-GUI工具的使用方式非常简单,运行程序后,选择File-->Open File
,选择一个class文件即可。
Lombok验证
我们将通过Java Decompiler
工具将Lombok修改后的class文件反编译出来,查看源代码来验证各个注解的作用,以便做到心中有数。在学习和接触一门新知识的时候也应该要对它做到心中有数,避免在实际工作中产生一些线上故障。
Lombok实战
lombok常用注解
更多注解请访问:https://projectlombok.org/features/all
@Getter和@Setter
可以注解在类上或者属性上,注解在类上会为类的所有非静态属性生成getter或者setter方法。
@Setter(AccessLevel.PROTECTED):
AccessLevel表示访问级别,默认为public
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
//为类的所有属性提供getter方法
@Getter
public class Person {
private String name;
//为age属性提供protected的setter方法
@Setter(AccessLevel.PROTECTED)
private Integer age;
}
通过反编译工具查看Person.class的内容,如图,与我们的预期效果一致
@NoArgsConstructor和@AllArgsConstructor
通常两个注解会一起使用,因为只有定义了带参构造才需要显示声明无参构造。
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public class Person {
private String name;
private Integer age;
}
通过反编译工具查看Person.class的内容,内容如下
public class Person{
private String name;
private Integer age;
@ConstructorProperties({"name", "age"})
public Person(String name, Integer age){
this.name = name; this.age = age;
}
public Person(){}
}
@ToString和@EqualsAndHashCode
这两个注解默认会使用全部属性作为参数去重写相应的方法,可以通过of
和exclude
属性来控制。
@ToString(of = "column"):
of代表只需要某个或者多个属性
@ToString(exclude = {"column", "column2"}):
exclude代表排除某个或者多个属性
@EqualsAndHashCode的用法同上。
import java.util.Date;
import lombok.EqualsAndHashCode;
import lombok.ToString;
//只使用name属性重写2equals方法和hashCode方法
@EqualsAndHashCode(of = "name")
//使用除了age和birthday的其他属性重写toString方法
@ToString(exclude = {"age", "birthday"})
public class Person {
private String name;
private Integer age;
private Date birthday;
}
通过反编译工具查看Person.class的内容,内容如下
public class Person {
private String name;
private Integer age;
private Date birthday;
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Person))
return false;
Person other = (Person) o;
if (!other.canEqual(this))
return false;
Object this$name = this.name;
Object other$name = other.name;
return this$name == null ? other$name == null : this$name.equals(other$name);
}
protected boolean canEqual(Object other) {
return other instanceof Person;
}
public int hashCode() {
int PRIME = 59;
int result = 1;
Object $name = this.name;
result = result * 59 + ($name == null ? 43 : $name.hashCode());
return result;
}
public String toString() {
return "Person(name=" + this.name + ")";
}
}
@Data
同时包含了注解@Getter、@Setter、@EqualsAndHashCode、@ToString,也就是说会为类的所有非静态属性提供getter和setter方法,并且使用所有属性重写equals方法、hashCode方法和toString方法。
@Slf4j和@Log4j
这两个注解都会提供变量名为log的日志对象,使用@SIf4j
还是@Log4j
看项目使用的日志框架。
使用注解就等同于在类中定义:private Logger log = LoggerFactory.getLogger(类名.class);
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class UserServiceImpl implements IUserService {
public void addUser(User user){
log.info("添加用户服务");
}
}
后序
使用lombok虽然能够省去手动创建setter和getter等方法的繁琐,但是却降低了源代码文件的可读性和完整性,降低了阅读源代码的舒适度。根据个人喜好和实际需要进行取舍。
在实际工作中选择适合的地方使用Lombok,例如POJO是一个好地方, 因为POJO很单纯。