不飞则已,一飞冲天;不鸣则已,一鸣惊人。这篇文章主要讲述认识Java项目开发效率工具 Lombok相关的知识,希望能为你提供帮助。
引言
在通常的java项目中,充斥着太多不友好的代码:POJO的getter/setter/toString;异常处理;I/O流的关闭操作等等,这些样板代码既没有技术含量,又影响着代码的美观,Lombok应运而生。
而 IDEA 2020 版本中,已经内置了Lombok插件,SpringBoot 2.1.x之后的版本也在Starter中内置了Lombok依赖。今天来讲讲Lombok的使用,看看它有何神奇之处!
Lombok的安装配置
使用 Lombok 之前我们先要在所使用的 IDE 中进行集成安装,这里以 IDEA 为例,安装步骤十分简单:
- 前往
File -& gt; Settings -& gt; Plugin -& gt; Marketplace
,搜索 Lombok,并安装
文章图片
- 选择搜索结果 Lombok ,点击 Install 安装。
- 安装完成后重启即可。
pom.xml
文件中添加 Lombok 的依赖进行使用了。<
dependency>
<
groupId>
org.projectlombok<
/groupId>
<
artifactId>
lombok<
/artifactId>
<
optional>
true<
/optional>
<
/dependency>
Lombok的常用注解
1. @Data
@Data
是一个方便使用的组合注解,是 @ToString
、@EqualsAndHashCode
、@Getter
、@Setter
和 @RequiredArgsConstructor
的组合体。@Data
public class DemoUser {
private String userId;
private String userName;
private String userAge;
}
编译后Lombok会生成如下代码:
public class DemoUser {
private String userId;
private String userName;
private String userAge;
public DemoUser() {
}public String getUserId() {
return this.userId;
}public String getUserName() {
return this.userName;
}public String getUserAge() {
return this.userAge;
}public void setUserId(String userId) {
this.userId = userId;
}public void setUserName(String userName) {
this.userName = userName;
}public void setUserAge(String userAge) {
this.userAge = userAge;
}public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof DemoUser)) {
return false;
} else {
DemoUser other = (DemoUser)o;
if (!other.canEqual(this)) {
return false;
} else {
label47: {
Object this$userId = this.getUserId();
Object other$userId = other.getUserId();
if (this$userId == null) {
if (other$userId == null) {
break label47;
}
} else if (this$userId.equals(other$userId)) {
break label47;
}return false;
}Object this$userName = this.getUserName();
Object other$userName = other.getUserName();
if (this$userName == null) {
if (other$userName != null) {
return false;
}
} else if (!this$userName.equals(other$userName)) {
return false;
}Object this$userAge = this.getUserAge();
Object other$userAge = other.getUserAge();
if (this$userAge == null) {
if (other$userAge != null) {
return false;
}
} else if (!this$userAge.equals(other$userAge)) {
return false;
}return true;
}
}
}protected boolean canEqual(Object other) {
return other instanceof DemoUser;
}public int hashCode() {
int PRIME = true;
int result = 1;
Object $userId = this.getUserId();
int result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
Object $userName = this.getUserName();
result = result * 59 + ($userName == null ? 43 : $userName.hashCode());
Object $userAge = this.getUserAge();
result = result * 59 + ($userAge == null ? 43 : $userAge.hashCode());
return result;
}public String toString() {
return "DemoUser(userId=" + this.getUserId() + ", userName=" + this.getUserName() + ", userAge=" + this.getUserAge() + ")";
}
}
2.@Value使用
@Value
注解可以把类声明为不可变的,声明后此类相当于 final
类,无法被继承,其属性也会变成 final
属性。@Value
public class DemoUser {
private final String userId;
private final String userName;
private final String userAge;
}
编译后Lombok会生成如下代码:
public final class DemoUser {
private final String userId;
private final String userName;
private final String userAge;
public DemoUser(String userId, String userName, String userAge) {
this.userId = userId;
this.userName = userName;
this.userAge = userAge;
}public String getUserId() {
return this.userId;
}public String getUserName() {
return this.userName;
}public String getUserAge() {
return this.userAge;
}public boolean equals(Object o) {
if (o == this) {
return true;
} else if (!(o instanceof DemoUser)) {
return false;
} else {
DemoUser other;
label44: {
other = (DemoUser)o;
Object this$userId = this.getUserId();
Object other$userId = other.getUserId();
if (this$userId == null) {
if (other$userId == null) {
break label44;
}
} else if (this$userId.equals(other$userId)) {
break label44;
}return false;
}Object this$userName = this.getUserName();
Object other$userName = other.getUserName();
if (this$userName == null) {
if (other$userName != null) {
return false;
}
} else if (!this$userName.equals(other$userName)) {
return false;
}Object this$userAge = this.getUserAge();
Object other$userAge = other.getUserAge();
if (this$userAge == null) {
if (other$userAge != null) {
return false;
}
} else if (!this$userAge.equals(other$userAge)) {
return false;
}return true;
}
}public int hashCode() {
int PRIME = true;
int result = 1;
Object $userId = this.getUserId();
int result = result * 59 + ($userId == null ? 43 : $userId.hashCode());
Object $userName = this.getUserName();
result = result * 59 + ($userName == null ? 43 : $userName.hashCode());
Object $userAge = this.getUserAge();
result = result * 59 + ($userAge == null ? 43 : $userAge.hashCode());
return result;
}public String toString() {
return "DemoUser(userId=" + this.getUserId() + ", userName=" + this.getUserName() + ", userAge=" + this.getUserAge() + ")";
}
}
3.@Slf4j使用 Lombok 生成日志对象时,根据使用日志实现的不同,有多种注解可以使用。比如
@Log
、@Log4j
、@Log4j2
、@Slf4j
等。@Value
public class DemoUser {
private final String userId;
private final String userName;
private final String userAge;
}
编译后Lombok会生成如下代码:
public class DemoUser {
private static final Logger log = LoggerFactory.getLogger(DemoUser.class);
private String userId;
private String userName;
private String userAge;
public DemoUser() {
}
}
4.@Builder使用
@Builder
注解可以通过建造者模式来创建对象,建造者模式加链式调用,创建对象非常方便。@Builder
public class DemoUser {
private final String userId;
private final String userName;
private final String userAge;
}
编译后Lombok会生成如下代码:
public class DemoUser {
private final String userId;
private final String userName;
private final String userAge;
DemoUser(String userId, String userName, String userAge) {
this.userId = userId;
this.userName = userName;
this.userAge = userAge;
}public static DemoUser.DemoUserBuilder builder() {
return new DemoUser.DemoUserBuilder();
}public static class DemoUserBuilder {
private String userId;
private String userName;
private String userAge;
DemoUserBuilder() {
}public DemoUser.DemoUserBuilder userId(String userId) {
this.userId = userId;
return this;
}public DemoUser.DemoUserBuilder userName(String userName) {
this.userName = userName;
return this;
}public DemoUser.DemoUserBuilder userAge(String userAge) {
this.userAge = userAge;
return this;
}public DemoUser build() {
return new DemoUser(this.userId, this.userName, this.userAge);
}public String toString() {
return "DemoUser.DemoUserBuilder(userId=" + this.userId + ", userName=" + this.userName + ", userAge=" + this.userAge + ")";
}
}
}
Lombok的原理
如果IDEA不安装Lombok插件的话,我们打开使用Lombok的项目是无法通过编译的。装了以后IDEA才会提示我们Lombok为我们生成的方法和属性。
使用了@Data注解以后,查看类结构可以发现getter、setter、toString等方法。
自Java 6起,javac开始支持JSR 269 Pluggable Annotation Processing API规范,只要程序实现了该API,就能在java源码编译时调用定义的注解。举例来讲,如今有一个实现了" JSR 269 API" 的程序A,那么使用javac编译源码的时候具体流程以下:
- javac对源代码进行分析,生成一棵抽象语法树(AST);插件
- 运行过程当中调用实现了" JSR 269 API" 的A程序;
- 此时A程序就能够完成它本身的逻辑,包括修改第一步骤获得的抽象语法树(AST);
- javac使用修改后的抽象语法树(AST)生成字节码文件;
详细的流程图以下:
文章图片
【认识Java项目开发效率工具 Lombok】从上面的Lombok执行的流程图中能够看出,在Javac 解析成AST抽象语法树以后, Lombok 根据本身编写的注解处理器,动态地修改 AST,增长新的节点(即Lombok自定义注解所须要生成的代码),最终经过分析生成JVM可执行的字节码Class文件。使用AnnotationProcessing自定义注解是在编译阶段进行修改,而jdk的反射技术是在运行时动态修改,二者相比,反射虽然更加灵活一些可是带来的性能损耗更加大。
- 在开发工具中,使用Lombok注解省略的方法在被调用时,会报找不到定义的错误,此种状况下,须要作些特殊处理;
- 使用Lombok虽然可以省去手动建立
setter
和getter
等方法的麻烦,可是却大大下降了源码的可读性和完整性,下降了阅读源代码的温馨度。
推荐阅读
- 一篇超详细的vue项目前端自动化测试教学!
- prometheusblackbox_exporter
- MongoDB认证与授权
- kube-eventer事件监控
- 你会用ES6,那倒是用啊!
- 想了解Xtrabackup备份原理和常见问题分析,看这篇就够了
- Dynamics 365层级数据的定义展示与查询
- 实体关联起来查询可以不通过关系(Lookup字段)吗()
- Flutter 多引擎支持 PlatformView 以及线程合并解决方案