lombok简介
Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注解,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。
lombok官网地址:Project Lombok
lombok maven坐标
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
lombok 注解
@Data 注解
定义一个Person 类,使用@Data注解
@Data
public class Person {
private Integer id;
private String name;
private Date birthday;
}
编译后,生成的Person.class 文件
import java.util.Date;
public class Person {
private Integer id;
private String name;
private Date birthday;
public Person() {
}
public Integer getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Date getBirthday() {
return this.birthday;
}
public void setId(final Integer id) {
this.id = id;
}
public void setName(final String name) {
this.name = name;
}
public void setBirthday(final Date birthday) {
this.birthday = birthday;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Person)) {
return false;
} else {
Person other = (Person)o;
if (!other.canEqual(this)) {
return false;
} else {
label47: {
Object this$id = this.getId();
Object other$id = other.getId();
if (this$id == null) {
if (other$id == null) {
break label47;
}
} else if (this$id.equals(other$id)) {
break label47;
}
return false;
}
Object this$name = this.getName();
Object other$name = other.getName();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}
Object this$birthday = this.getBirthday();
Object other$birthday = other.getBirthday();
if (this$birthday == null) {
if (other$birthday != null) {
return false;
}
} else if (!this$birthday.equals(other$birthday)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof Person;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $id = this.getId();
int result = result * 59 + ($id == null ? 43 : $id.hashCode());
Object $name = this.getName();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
Object $birthday = this.getBirthday();
result = result * 59 + ($birthday == null ? 43 : $birthday.hashCode());
return result;
}
public String toString() {
return "Person(id=" + this.getId() + ", name=" + this.getName() + ", birthday=" + this.getBirthday() + ")";
}
}
可以看出@Data注解,可以生产get set equals hashCode toString等方法。
@Getter 和 @Setter注解
@Getter
@Setter
public class Person {
private Integer id;
private String name;
private Date birthday;
}
编译后生成的.class文件
import java.util.Date;
public class Person {
private Integer id;
private String name;
private Date birthday;
public Person() {
}
public Integer getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Date getBirthday() {
return this.birthday;
}
public void setId(final Integer id) {
this.id = id;
}
public void setName(final String name) {
this.name = name;
}
public void setBirthday(final Date birthday) {
this.birthday = birthday;
}
}
@ToString注解
@Getter
@ToString
public class Person {
private Integer id;
private String name;
private Date birthday;
}
编译后,生成的.class文件
import java.util.Date;
public class Person {
private Integer id;
private String name;
private Date birthday;
public Person() {
}
public Integer getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Date getBirthday() {
return this.birthday;
}
public String toString() {
return "Person(id=" + this.getId() + ", name=" + this.getName() + ", birthday=" + this.getBirthday() + ")";
}
}
@NoArgsConstructor 和 @AllArgsConstructor 注解
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Person {
private Integer id;
private String name;
private Date birthday;
}
编译后,生成的.class文件
import java.util.Date;
public class Person {
private Integer id;
private String name;
private Date birthday;
public Integer getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Date getBirthday() {
return this.birthday;
}
public Person() {
}
public Person(final Integer id, final String name, final Date birthday) {
this.id = id;
this.name = name;
this.birthday = birthday;
}
}
@Accessors 注解
@Data
@Accessors(chain = true, fluent = true)
public class Person {
private Integer id;
private String name;
private Date birthday;
}
编译后,生成的.class文件
import java.util.Date;
public class Person {
private Integer id;
private String name;
private Date birthday;
public Person() {
}
public Integer id() {
return this.id;
}
public String name() {
return this.name;
}
public Date birthday() {
return this.birthday;
}
public Person id(final Integer id) {
this.id = id;
return this;
}
public Person name(final String name) {
this.name = name;
return this;
}
public Person birthday(final Date birthday) {
this.birthday = birthday;
return this;
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof Person)) {
return false;
} else {
Person other = (Person)o;
if (!other.canEqual(this)) {
return false;
} else {
label47: {
Object this$id = this.id();
Object other$id = other.id();
if (this$id == null) {
if (other$id == null) {
break label47;
}
} else if (this$id.equals(other$id)) {
break label47;
}
return false;
}
Object this$name = this.name();
Object other$name = other.name();
if (this$name == null) {
if (other$name != null) {
return false;
}
} else if (!this$name.equals(other$name)) {
return false;
}
Object this$birthday = this.birthday();
Object other$birthday = other.birthday();
if (this$birthday == null) {
if (other$birthday != null) {
return false;
}
} else if (!this$birthday.equals(other$birthday)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof Person;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $id = this.id();
int result = result * 59 + ($id == null ? 43 : $id.hashCode());
Object $name = this.name();
result = result * 59 + ($name == null ? 43 : $name.hashCode());
Object $birthday = this.birthday();
result = result * 59 + ($birthday == null ? 43 : $birthday.hashCode());
return result;
}
public String toString() {
return "Person(id=" + this.id() + ", name=" + this.name() + ", birthday=" + this.birthday() + ")";
}
}
lombok原理
我们先看下lombok的maven 坐标导入
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
<scope>provided</scope>
</dependency>
maven 的 scope 范围
- compile 的范围:当我们在pom.xml文件中的<scope></scope>标签中依赖为compile的时候,会在编译的时候将这个依赖加入进来,并且在打包(mvn package)的时候也会将这个依赖加入进去。简单来说就是编译和打包的时候直接加入,其他时候不会加入。
- provided的范围 :在编译和测试的时候有效,在执行(mvn package)进行打包jar或者war包的时候不会加入,如果加入会出现包的冲突。
- test的范围:意思是在测试的时候才会真正生效,但是其他的时候就不会,比如单元测试的时候你加入@Test注解时候会自己生效的,不用管它。
- runtime的范围:同理在运行的时候才会依赖,在编译的时候不会依赖啦。
lombok的scope 范围是provided,那么在mvn package时不会加入。
@Retention 详解
@Data注解代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Data {
/**
* If you specify a static constructor name, then the generated constructor will be private, and
* instead a static factory method is created that other classes can use to create instances.
* We suggest the name: "of", like so:
*
* <pre>
* public @Data(staticConstructor = "of") class Point { final int x, y; }
* </pre>
*
* Default: No static constructor, instead the normal constructor is public.
*
* @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticConstructor() default "";
}
@Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中
- source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略。
- class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期。
- runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在
这3个生命周期分别对应于:Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码。
lombok 编译流程
自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。Lombok就是一个实现了"JSR 269 API"的程序。在使用javac的过程中,它产生作用的具体流程如下:
- javac对源代码进行分析,生成一棵抽象语法树(AST)。
- javac编译过程中调用实现了JSR 269的Lombok程序
- 此时Lombok就对第一步骤得到的AST进行处理,找到Lombok注解所在类对应的语法树 (AST),然后修改该语法树(AST),增加Lombok注解定义的相应树节点。
- javac使用修改后的抽象语法树(AST)生成字节码文件。
参考:
https://www.jianshu.com/p/29a08cb44b16
Lombok的基本使用 - 简书