Lombok使用与原理
Lombok使用与原理
1. Lombok简介
首先 Lombok
是一款Java IDE的应用工具插件,一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,比如属性的构造器、getter、setter、equals、hashcode、toString方法。结合IDE,通过使用对应的注解,可以在编译源码的时候生成对应的方法。官方地址: https://projectlombok.org/
。
虽然上述的那些常用方法IDE都能生成,但是lombok更加简洁与方便,能够达到的效果就是在源码中不需要写一些通用的方法,但是在编译生成的字节码文件中会帮我们生成这些方法,这就是lombok的神奇作用。
2. 安装
2.1 插件安装
笔者主要使用的IDE是Intellij idea,编译器需要在
preference->plugins->Browse repositories
搜索lombok,然后安装plugins,需要稍等片刻。笔者截图已经安装好。
2.2 添加jar包
在项目中添加lombok的jar包,笔者用的是maven,所以在pom文件中添加了如下的依赖。gradle使用见官网。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
<scope>provided</scope>
</dependency>
3. 使用
lombok主要通过注解起作用,详细的注解见Lombok features。
With Lombok:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
public class UserEntity implements Serializable {
private long userId;
private String userName;
private String sex;
}
编译后:
import java.beans.ConstructorProperties;
import java.io.Serializable;
public class UserEntity implements Serializable {
private long userId;
private String userName;
private String sex;
public long getUserId() {
return this.userId;
}
public String getUserName() {
return this.userName;
}
public String getSex() {
return this.sex;
}
public void setUserId(long userId) {
this.userId = userId;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setSex(String sex) {
this.sex = sex;
}
public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof UserEntity)) {
return false;
} else {
UserEntity other = (UserEntity)o;
if(!other.canEqual(this)) {
return false;
} else if(this.getUserId() != other.getUserId()) {
return false;
} else {
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$sex = this.getSex();
Object other$sex = other.getSex();
if(this$sex == null) {
if(other$sex != null) {
return false;
}
} else if(!this$sex.equals(other$sex)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(Object other) {
return other instanceof UserEntity;
}
public int hashCode() {
int PRIME = true;
int result = 1;
long $userId = this.getUserId();
int result = result * 59 + (int)($userId >>> 32 ^ $userId);
Object $userName = this.getUserName();
result = result * 59 + ($userName == null?43:$userName.hashCode());
Object $sex = this.getSex();
result = result * 59 + ($sex == null?43:$sex.hashCode());
return result;
}
public String toString() {
return "UserEntity(userId=" + this.getUserId() + ", userName=" + this.getUserName() + ", sex=" + this.getSex() + ")";
}
@ConstructorProperties({"userId", "userName", "sex"})
public UserEntity(long userId, String userName, String sex) {
this.userId = userId;
this.userName = userName;
this.sex = sex;
}
}
这边介绍笔者经常使用到的注解。
- val,用在局部变量前面,相当于将变量声明为final
- @Value
用在类上,是@Data的不可变形式,相当于为属性添加final声明,只提供getter方法,而不提供setter方法
- @Data
提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法。通常情况下,我们使用这个注解就足够了。
- @NoArgsConstructor无参构造器
- @AllArgsConstructor全参构造器
- @ToString
生成toString方法,默认情况下,会输出类名、所有属性,属性会按照顺序输出,以逗号分割。
- @EqualsAndHashCode
默认情况下,会使用所有非瞬态(non-transient)和非静态(non-static)字段来生成equals和hascode方法,也可以指定具体使用哪些属性。
- @Getter / @Setter
上面已经说过,一般用@data就不用额外加这个注解了。可以作用在类上 和属性上,放在类上,会对所有的非静态(non-static)属性生成Getter/Set ter方法,放在属性上,会对该属性生成Getter/Setter方法。并可以指定Getter/Setter方法的访问级别。
- @NonNull,给方法参数增加这个注解会自动在方法内对该参数进行是否为空的校验,如果为空,则抛出NPE(NullPointerException)。
- @Cleanup 自动管理资源,用在局部变量之前,在当前变量范围内即将执行完毕退出之前会自动清理资源,自动生成try-finally这样的代码来关闭流。
- @Log
根据不同的注解生成不同类型的log对象,但是实例名称都是log,有7种可选实现类:
1). @Log4j
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
2). @Log4j2
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
3). @Slf4j
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
4). @XSlf4j
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
5). @CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
6). @JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
7). @Log
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
默认情况下,logger的名字将会是被@Log注解的那个类的名字。当然这也可以被个性化命名,通过topic参数,如 @XSlf4j(topic="reporting")
。
4. 原理
lombok 主要通过注解生效,自jdk5引入注解,由两种解析方式。
第一种是运行时解析, @Retention(RetentionPolicy.RUNTIME)
, 定义注解的保留策略,这样可以通过反射拿到该注解。
另一种是编译时解析,有两种机制。
- Annotation Processing Tool,apt自JDK5产生,JDK7已标记为过期,不推荐使用,JDK8中已彻底删除,自JDK6开始,可以使用Pluggable Annotation Processing API来替换它,apt被替换主要有2点原因。api都在com.sun.mirror非标准包下,还有就是没有集成到javac中,需要额外运行。
- Pluggable Annotation Processing API lombok使用这种方式实现,基于JSR 269,自JDK6加入,作为apt的替代方案,它解决了apt的两个问题,javac在执行的时候会调用实现了该API的程序,这样我们就可以对编译器做一些增强,这时javac执行的过程如下:
5. 总结
这篇文章主要讲解了lombok的入门与使用。介绍了一些常用的lombok注解,大大简化了我们的开发工作和代码的简洁性。当然,lombok不支持多种参数构造器的重载,工具毕竟是工具,我感觉并不会有非常完美适合每个人的工具。最后,我个人还是很推荐这款插件的,毕竟我很懒,?。
参考
- Lombok Docs
- Java奇淫巧技之Lombok
- PHP-超级全局变量
- 日志分析实战之清洗日志小实例5:实现获取不能访问url
- CentOS安装Redis、PHPredis扩展
- 日志分析实战之清洗日志小实例4:统计网站相关信息
- PHP-数组排序
- hdu---(3555)Bomb(数位dp(入门))
- PHP-循环
- 日志分析实战之清洗日志小实例3:如何在spark shell中导入自定义包
- PHP-函数
- hdu----(5045)Contest(数位dp)
- hdu----(5053)the Sum of Cube(签到题,水体)
- RHEL构建DNS服务器-多区域
- hdu----(5050)Divided Land(二进制求最大公约数)
- 日志分析实战之清洗日志小实例1:使用spark&Scala分析Apache日志
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 定义一个函数,在该函数中可以实现任意两个整数的加法。java实现
- JDBC连接ORACLE的三种URL格式
- Centreon+Nagios实战第八篇——Nagios+Centreon添加监控服务
- Centreon+Nagios实战第九篇——利用nrpe插件监控本机
- 第四篇 CentOs7下安装Zabbix
- 第十三篇 zabbix创建Item
- 第十四篇 zabbix创建自定义Item
- 【性能】688- 前端性能优化——从 10 多秒到 1.05 秒
- 第十六篇 zabbix创建Trigger
- 如何通过程序(java代码)提高你的博客访问量
- zabbix_get [12429]: Check access restrictions in Zabbix agent configuration
- 【设计模式】689- TypeScript 设计模式之观察者模式
- Found a swap file by the name ".jsidInspector.py.swp"
- CentOs7下部署tomcat文件服务器
- 【拓展】未来的JavaScript记录与元组