原理
Lombok主要作用于编译阶段,从JDK1.6开始,javac可以处理遵循《JSR 269 Pluggable Annotation Processing API》规范的注解,Lombok的注解处理器就可以在编译阶段被调用。
大致流程如下:
- javac对源代码进行分析,生成一棵抽象语法树(AST)
- javac编译过程中调用遵循JSR 269规范的Lombok注解处理器
- Lombok注解处理器获取到需要处理的AST
- Lombok注解处理器找到Lombok注解,生成对应的代码,修改对应的AST,生成新的AST
- javac使用新的AST生成字节码文件
安装使用
Lombok需要安装,使用命令行:
java -jar lombok.jar
然后有图形界,可以看到在自动查找IDE,这种方式主要是针对Eclipse。
如果不行,就eclipse.ini手动添加:
; 在启动类路径中添加的Lombok
-Xbootclasspath/D:lombok.jar
; 设置代理
-javaagent:lombok.jar
如果是IDEA,那么就直接通过Marketplace安装。
安装之后,有依赖Lombok的项目就会自动配置,如果没有就需要手动配置一下。
maven配置
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
<repositories>
<repository>
<id>projectlombok.org</id>
<url>http://projectlombok.org/mavenrepo</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</build>
常用注解
注解 | 注解目标 | 说明 |
---|---|---|
@Log | 类 | 生成日志变量,@Log、@Slf4j、@Log4j、@Log4j2等 |
@Data | 类 | 大礼包,包含@ToString、@EqualsAndHashCode、@Getter、@Setter、@RequiredArgsConstructor |
@Getter | 类或成员变量 | 生成getter方法 |
@Setter | 类或成员变量 | 生成setter方法 |
@NonNull | 成员变量和参数 | 变量参数不能为空,否则抛出空指针异常 |
@Builder | 类 | 将类转变为建造者模式 |
@Cleanup | 变量 | 自动关闭资源,实现java.io.Closeable接口才有效 |
@ToString | 类 | 覆盖toString()方法,of包含字段、exclude排除属性排除字段 |
@SneakyThrows | 方法 | 捕捉并抛出受检异常 |
@Synchronized | 方法 | 和Java自己的synchronized基本一样,实际就是通过synchronized关键字来实现 |
@EqualsAndHashCode | 类 | 覆盖equals和hashCode方法 |
@NoArgsConstructor | 类 | 生成无参构造函数 |
@AllArgsConstructor | 类 | 生成全参构造函数 |
@RequiredArgsConstructor | 类 | 生成包含final和@NonNull注解的成员变量的构造函数 |
实例说明
一个简单的例子,可以看一下,Lombok注解器对不同的注解都生成了什么样的代码。
import lombok.Builder;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import java.sql.Date;
import java.sql.SQLDataException;
@Data
@Slf4j
@Builder
public class User {
private Integer id;
private String name;
private Date birthday;
@Synchronized
public void doSomethingA(){
}
@SneakyThrows
public void doSomethingB(){
throw new SQLDataException();
}
}
Lombok处理后的代码:
import java.sql.Date;
import java.sql.SQLDataException;
public class User {
@java.lang.SuppressWarnings("all")
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(User.class);
@java.lang.SuppressWarnings("all")
private final java.lang.Object $lock = new java.lang.Object[0];
private Integer id;
private String name;
private Date birthday;
public void doSomethingA() {
synchronized (this.$lock) {
}
}
public void doSomethingB() {
try {
throw new SQLDataException();
} catch (final java.lang.Throwable $ex) {
throw lombok.Lombok.sneakyThrow($ex);
}
}
@java.lang.SuppressWarnings("all")
User(final Integer id, final String name, final Date birthday) {
this.id = id;
this.name = name;
this.birthday = birthday;
}
@java.lang.SuppressWarnings("all")
public static class UserBuilder {
@java.lang.SuppressWarnings("all")
private Integer id;
@java.lang.SuppressWarnings("all")
private String name;
@java.lang.SuppressWarnings("all")
private Date birthday;
@java.lang.SuppressWarnings("all")
UserBuilder() {
}
@java.lang.SuppressWarnings("all")
public User.UserBuilder id(final Integer id) {
this.id = id;
return this;
}
@java.lang.SuppressWarnings("all")
public User.UserBuilder name(final String name) {
this.name = name;
return this;
}
@java.lang.SuppressWarnings("all")
public User.UserBuilder birthday(final Date birthday) {
this.birthday = birthday;
return this;
}
@java.lang.SuppressWarnings("all")
public User build() {
return new User(this.id, this.name, this.birthday);
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
return "User.UserBuilder(id=" + this.id + ", name=" + this.name + ", birthday=" + this.birthday + ")";
}
}
@java.lang.SuppressWarnings("all")
public static User.UserBuilder builder() {
return new User.UserBuilder();
}
@java.lang.SuppressWarnings("all")
public Integer getId() {
return this.id;
}
@java.lang.SuppressWarnings("all")
public String getName() {
return this.name;
}
@java.lang.SuppressWarnings("all")
public Date getBirthday() {
return this.birthday;
}
@java.lang.SuppressWarnings("all")
public void setId(final Integer id) {
this.id = id;
}
@java.lang.SuppressWarnings("all")
public void setName(final String name) {
this.name = name;
}
@java.lang.SuppressWarnings("all")
public void setBirthday(final Date birthday) {
this.birthday = birthday;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof User)) return false;
final User other = (User) o;
if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$id = this.getId();
final java.lang.Object other$id = other.getId();
if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
final java.lang.Object this$birthday = this.getBirthday();
final java.lang.Object other$birthday = other.getBirthday();
if (this$birthday == null ? other$birthday != null : !this$birthday.equals(other$birthday)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
protected boolean canEqual(final java.lang.Object other) {
return other instanceof User;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public int hashCode() {
final int PRIME = 59;
int result = 1;
final java.lang.Object $id = this.getId();
result = result * PRIME + ($id == null ? 43 : $id.hashCode());
final java.lang.Object $name = this.getName();
result = result * PRIME + ($name == null ? 43 : $name.hashCode());
final java.lang.Object $birthday = this.getBirthday();
result = result * PRIME + ($birthday == null ? 43 : $birthday.hashCode());
return result;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
return "User(id=" + this.getId() + ", name=" + this.getName() + ", birthday=" + this.getBirthday() + ")";
}
}
如果想要看更多注解生成的代码,可以自己动手实验一下,使用下面的delombok获取Lombok处理之后的Java源代码。
delombok
通过delombok可以查看编译之后的Java源文件是咋样的。
# 编译整个src目录
java -jar lombok.jar delombok src -d src-delomboked
# 打印编译之后的Java文件
java -jar lombok.jar delombok -p MyJavaSourceFile.java
java -jar lombok.jar delombok -p E:\workspace\learning\src\main\java\org\curitis\lombok\User.java
文档资料
annotation-process
github
Lombok注解
Lombok下载
delombok
Lombok开始