Lombok介绍:

Lombok其实就是取名自龙目岛(Pulau Lombok),龙目岛是印度尼西亚西努沙登加拉(Nusa Tenggara Barat)省岛屿,西隔龙目海峡面对巴厘岛,东隔阿拉斯(Alas)海峡面松巴哇(Sumbawa)岛,北濒爪哇海,南临印度洋。

在编程上,Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法。简而言之,一句话就是:通过简单的注解来精简代码达到消除冗长代码的目的。

Lombok优点:

提高编码效率

使代码更简洁

消除冗长代码

避免修改字段名字时忘记修改方法名

注:IDE上必须要支持Lombok,否则IDE会报错。

为什么说Lombok可以使代码更简洁、可以消除冗长代码呢?我们来拿lombok官网的一个例子来说:

public class Mountain{

private String name;

private double longitude;

private String country;

}

要使用这个对象,必须还要写一些getter和setter方法,可能还要写一个构造器、equals方法、或者hash方法。这些方法很冗长而且没有技术含量,我们叫它样板式代码。

lombok的主要作用是通过一些注解,消除样板式代码,像这样:

@Data

public class Mountain{

private String name;

private double longitude;

private String country;

}

然后可以看到这个类自动生成了这些方法:

如果觉得@Data这个注解有点简单粗暴的话,Lombok提供一些更精细的注解,比如@Getter、@Setter,(这两个是field注解),@ToString,@AllArgsConstructor(这两个是类注解)。这些可能是最常见的用法,更详细的用法可以参考[Lombok feature]overview(https://projectlombok.org/features/)

Lombok既是一个IDE插件,也是一个项目要依赖的jar包。Lombok是依赖jar包的原因是因为编译时要用它的注解。是插件的原因是他要在编译器编译时通过操作AST(抽象语法树)改变字节码生成。也就是说他可以改变java语法.。他不像spring的依赖注入或者hibernate的orm一样是运行时的特性,而是编译时的特性。

Lombok原理:

Lombok 实现了 JSR 269 Pluggable Annotation Processing API 规范,也就是可插拔注释处理

javac 从 JDK6 开始支持 “JSR 269 API” 规范

只要程序实现了该API,就能在javac运行的时候得到调用

而Lombok实现了 “JSR 269 API” 规范 ,在编译时,javac编译源码的具体流程如下:

1.javac对源代码(Source File)进行分析(Parse),生成一棵抽象语法树(AST)

2.运行过程(Annotation Processing)中调用实现了 "JSR 269 API" 的Lombok程序(Lombok Annotation Processor)

3.此时Lombok就对第一步骤得到的AST进行处理(Lombok Annotation Handler),找到@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),增加getter和setter方法定义的相应树节点

4.javac使用修改后的抽象语法树(Modified AST)进行分析生成(Analyze and Generate)字节码文件(Byte Code)

添加Lombok到项目中

创建一个Maven项目,通过pom.xml配置Lombok依赖到项目中,配置依赖如下:

org.projectlombok

lombok

1.16.18

IDEA安装Lombok插件

然后还需要在IDE中安装Lombok插件,我这里使用的是IDEA,所以先以IDEA为例做演示。点击右上角的 File -> setting -> Plugins :

搜索Lombok Plugin进行安装:

安装完成后,重启IDEA:

Eclipse安装Lombok插件:

1.安装该插件时最好关闭Eclipse,然后在官网中下载lombok.jar,下载地址

2.将 lombok.jar 放在eclipse安装目录下,和 eclipse.ini 文件平级的。

3.双击运行 lombok.jar

如果没法直接双击运行的话,就在 lombok.jar 的目录下,打开cmd命令行,运行如下命令:

java -jar lombok.jar

如果以下提示的权限问题则使用管理员身份运行即可:

注:Mac/Linux 系统下则使用 sudo java -jar lombok.jar 命令进行运行即可,但是要确保执行用户有sudo权限。

成功运行后会弹框如下框,一开始可能会加载些东西,加载完成后界面如下:

安装成功后如下图:

打开Eclipse,看看是否已安装Lombok插件,如下则是安装成功:

Lombok注解

Lombok 常用的注解:

注解

描述

@Getter / @Setter

可以作用在类上和属性上,放在类上,会对所有的非静态(non-static)属性生成Getter/Setter方法,放在属性上,会对该属性生成Getter/Setter方法。并可以使用该注解中的AccessLevel属性来指定Getter/Setter方法的访问级别。

@ToString

生成toString方法,默认情况下,会输出类名、所有属性,属性会按照顺序输出,以逗号分割。可以使用该注解中的exclude属性来指定生成的toSpring方法不包含对象中的哪些字段,或者使用of属性来指定生成的toSpring方法只包含对象中的哪些字段

@EqualsAndHashCode

默认情况下,会使用所有非瞬态(non-transient)和非静态(non-static)字段来生成equals和hascode方法,也可以使用exclude或of属性。

@NoArgsConstructor

生成无参构造器

@RequiredArgsConstructor

会生成一个包含标识了@NonNull注解的变量的构造方法。生成的构造方法是private,如果想要对外提供使用的话,可以使用staticName选项生成一个static方法。

@AllArgsConstructor

生成全参构造器,当我们需要重载多个构造器的时候,Lombok就无能为力了。

@Slf4j

该注解是用来解决不用每次都写 private final Logger logger = LoggerFactory.getLogger(XXX.class); 这句代码的。使用的日志框架是LogBack

@Log4j

该注解也是用来解决不用每次都写日志对象声明语句的,从字面上也可以看出,使用的日志框架是log4j

@Data

该注解是 @ToString、@EqualsAndHashCode注解,和所有属性的@Getter注解, 以及所有non-final属性的@Setter注解的组合,通常情况下,我们使用这个注解就足够了。

以上只列出了部分常用注解,更多注解的使用方式,请参考 官网关于注解的文档

反编译大法

当我们想查看.class文件的源码时,可以使用Java反编译工具:

Java Decompiler

分为以下几类

JD-GUI,独立的图形化软件

JD-Eclipse,可以集成到Eclipse插件

JD-Intellij,可以集成到IDEA插件

这里提到反编译工具的原因是因为Lombok是编译时修改的抽象语法树,所以我们想查看编译后的.class文件的源码就需要使用反编译工具。这里所介绍到的 Java Decompiler 就是用来帮助我们在使用Lombok遇到问题时,去验证编译后的.class文件的。

使用Lombok时需要注意的点

在类需要序列化、反序列化时或者需要详细控制字段时,应该谨慎考虑是否要使用Lombok,因为在这种情况下容易出问题。例如:Jackson、Json 序列化

使用Lombok虽然能够省去手动创建setter和getter方法等繁琐事情,但是却降低了源代码文件的可读性和完整性,减低了阅读源代码的舒适度

使用@Slf4j还是@Log4j注解,需要根据实际项目中使用的日志框架来选择。

Lombok并非处处适用,我们需要选择适合的地方使用Lombok,例如pojo是一个好地方,因为pojo很单纯

Lombok实战

我这里拿之前项目中的一个 Category 类来做为演示的例子,在使用Lombok之前,这个类里是写了getter setter方法以及构造函数的。现在我们使用Lombok将代码改造如下:

package org.mmall.pojo;

import lombok.*;

import java.util.Date;

@Data

@NoArgsConstructor

@AllArgsConstructor

@EqualsAndHashCode(of = "id")

@ToString(exclude = "updateTime")

public class Category {

private Integer id;

private Integer parentId;

private String name;

private Boolean status;

private Integer sortOrder;

private Date createTime;

private Date updateTime;

}

编译后生成的代码如下,使用反编译工具进行查看:

//

// Source code recreated from a .class file by IntelliJ IDEA

// (powered by Fernflower decompiler)

//

package org.mmall.pojo;

import java.beans.ConstructorProperties;

import java.util.Date;

public class Category {

private Integer id;

private Integer parentId;

private String name;

private Boolean status;

private Integer sortOrder;

private Date createTime;

private Date updateTime;

public Integer getId() {

return this.id;

}

public Integer getParentId() {

return this.parentId;

}

public String getName() {

return this.name;

}

public Boolean getStatus() {

return this.status;

}

public Integer getSortOrder() {

return this.sortOrder;

}

public Date getCreateTime() {

return this.createTime;

}

public Date getUpdateTime() {

return this.updateTime;

}

public void setId(Integer id) {

this.id = id;

}

public void setParentId(Integer parentId) {

this.parentId = parentId;

}

public void setName(String name) {

this.name = name;

}

public void setStatus(Boolean status) {

this.status = status;

}

public void setSortOrder(Integer sortOrder) {

this.sortOrder = sortOrder;

}

public void setCreateTime(Date createTime) {

this.createTime = createTime;

}

public void setUpdateTime(Date updateTime) {

this.updateTime = updateTime;

}

public Category() {

}

@ConstructorProperties({"id", "parentId", "name", "status", "sortOrder", "createTime", "updateTime"})

public Category(Integer id, Integer parentId, String name, Boolean status, Integer sortOrder, Date createTime, Date updateTime) {

this.id = id;

this.parentId = parentId;

this.name = name;

this.status = status;

this.sortOrder = sortOrder;

this.createTime = createTime;

this.updateTime = updateTime;

}

public boolean equals(Object o) {

if (o == this) {

return true;

} else if (!(o instanceof Category)) {

return false;

} else {

Category other = (Category)o;

if (!other.canEqual(this)) {

return false;

} else {

Object this$id = this.getId();

Object other$id = other.getId();

if (this$id == null) {

if (other$id != null) {

return false;

}

} else if (!this$id.equals(other$id)) {

return false;

}

return true;

}

}

}

protected boolean canEqual(Object other) {

return other instanceof Category;

}

public int hashCode() {

int PRIME = true;

int result = 1;

Object $id = this.getId();

int result = result * 59 + ($id == null ? 43 : $id.hashCode());

return result;

}

public String toString() {

return "Category(id=" + this.getId() + ", parentId=" + this.getParentId() + ", name=" + this.getName() + ", status=" + this.getStatus() + ", sortOrder=" + this.getSortOrder() + ", createTime=" + this.getCreateTime() + ")";

}

}

如上,从反编译后的代码可以看到,getter setter方法和无参、全参构造器以及equals、hashcode、toString方法都生成出来了。在@EqualsAndHashCode注解中我们使用of属性指定只对比对象中id这个字段,所以生成的equals和hashcode只使用id这个字段作为因子,默认不指定的情况下是使用对象中所有的字段作为因子。而在@ToString注解中,我们使用exclude属性指定updateTime这字段不被输出,所以Lombok生成的toString方法中没有包含updateTime这个字段。

我们再来演示一下@Getter、@Setter以及@RequiredArgsConstructor注解的使用,新建一个测试类,编辑代码如下:

package org.mmall.pojo;

import lombok.Getter;

import lombok.NonNull;

import lombok.RequiredArgsConstructor;

import lombok.Setter;

@Getter

@Setter

@RequiredArgsConstructor(staticName = "getInstance")

public class Test {

private String name;

@NonNull

private int age;

}

编译后生成的代码如下,使用反编译工具进行查看:

//

// Source code recreated from a .class file by IntelliJ IDEA

// (powered by Fernflower decompiler)

//

package org.mmall.pojo;

import java.beans.ConstructorProperties;

import lombok.NonNull;

public class Test {

private String name;

@NonNull

private int age;

public String getName() {

return this.name;

}

@NonNull

public int getAge() {

return this.age;

}

public void setName(String name) {

this.name = name;

}

public void setAge(@NonNull int age) {

this.age = age;

}

@ConstructorProperties({"age"})

private Test(@NonNull int age) {

this.age = age;

}

public static Test getInstance(@NonNull int age) {

return new Test(age);

}

}

可以看到,@RequiredArgsConstructor注解会生成一个包含标识了@NonNull注解的变量的构造方法,并且生成的构造方法是private的,使用staticName选项可以生成一个可以得到该对象实例的static方法。

接下来演示一下@Slf4j注解的使用,因为我项目中使用的是logback,所以使用@Slf4j注解,如果使用的是log4j,则使用@Log4j注解,两者的使用方式是一样的。代码如下:

...

@Service("iCategoryService")

@Slf4j

public class CategoryServiceImpl implements ICategoryService {

public ServerResponse> getChildrenParallelCategory(Integer categoryId) {

List categoryList = categoryMapper.selectCategoryChildrenByParentId(categoryId);

if (CollectionUtils.isEmpty(categoryList)) {

log.info("未找到当前分类的子分类");

}

return ServerResponse.createBySuccess(categoryList);

}

}

编译后生成的代码如下,使用反编译工具进行查看:

...

@Service("iCategoryService")

public class CategoryServiceImpl implements ICategoryService {

private static final Logger log = LoggerFactory.getLogger(CategoryServiceImpl.class);

public ServerResponse> getChildrenParallelCategory(Integer categoryId) {

List categoryList = this.categoryMapper.selectCategoryChildrenByParentId(categoryId);

if (CollectionUtils.isEmpty(categoryList)) {

log.info("未找到当前分类的子分类");

}

return ServerResponse.createBySuccess(categoryList);

}

}

可以看到,Lombok会自动帮我们生成log对象的声明代码,这样我们就不需要总是每个类都去写这句代码了。

import lombok 报错_Lombok快速入门相关推荐

  1. import lombok 报错_lombok

    Lombok简介 Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,通过使用对应的注解,可以在编译源码的时候生成对应的方法.官方地址:https:/ ...

  2. import lombok 报错_Lombok注解@Getter @Setter详解

    1.为什么强大 ​项目中经常使用bean,entity等类,绝大部分数据类类中都需要get.set.toString.equals和hashCode方法,尽管IDE工具都会帮我们生成.但自动生成这些代 ...

  3. import lombok 报错_Android上使用Lombok和set、get方法告别

    一.前言 在项目中使用Lombok可以减少很多重复代码的书写.比如说getter/setter/toString等方法的编写.比如看下图我写的代码,一个@Data注解搞定,彻底抛弃set get方法. ...

  4. import lombok 报错_使用lombok

    Lombok是一种JavaArchive(JAR)文件,可用来消除Java代码的冗长.通过在开发环境中实现Lombok,开发人 员可以节省构建诸如hashCode()和equals()这样的方法以及以 ...

  5. from Crypto.Cipher import AES报错解决【WindowsLinux】

    文章目录 一.Crypto库 二.修改步骤 1.安装库 2.修改crypto为Crypto 3.Linux环境下解决报错 一.Crypto库 Crypto.Cipher包含保护机密数据的加密算法.具体 ...

  6. 在cmd下import cv2报错——OpenCV实现BRISK

    平台:win10 x64 +JetBrains PyCharm 2018.2.4 x64 +Anaconda3(python3.7.0+opencv3.4.5) Issue说明:同学发了个python ...

  7. windows10下,from skimage import morphology 报错的解决办法

    windows10下,from skimage import morphology 报错的解决办法 报错原因 没有安装numpy+mkl库 解决方法 卸载skimage pip uninstall s ...

  8. Windows anaconda python3 import ssl报错的解决方案

    Windows anaconda python3 import ssl报错的解决方案_dailinqing1984的博客-CSDN博客

  9. python import requests报错_import requests 出错,搜了很多,没解决,求教.

    requests 依赖的库都已经安装了. Requirement not upgraded as not directly required: chardet<3.1.0,>=3.0.2 ...

最新文章

  1. [BZOJ3693]圆桌会议[霍尔定理+线段树]
  2. 使用Word宏替换Header、Footer等中的文本
  3. 【转】ABP源码分析四十七:ABP中的异常处理
  4. 介绍Calico eBPF数据平面:Linux内核网络、安全性和跟踪(Kubernetes、kube-proxy)
  5. 940mx黑苹果驱动_让黑苹果变得更完美——BCM94532HMB无线蓝牙接力完美驱动!
  6. 全新防火墙6.0 单条PPPOE(ADSL)上网配置
  7. iis7网站可用php吗,在IIS7下面添加对PHP网页的支持
  8. java获取weblogic路径_weblogic下java web项目获取根路径
  9. Graph_editor——好用的画图软件,你会用吗?
  10. ubuntu18.04超级简单的安装wine QQ教程
  11. mysql实现axure协同工作_AxureUX CRM及协同办公APP高保真原型模板(带移动端实用元件库)...
  12. FastDFS原理及入门
  13. C或C++报错:ld returned 1 exit status报错的原因
  14. 从 拼多多 到 抖音
  15. python 优雅退出_Python学习教程:Python 使用 backoff 更优雅的实现轮询
  16. [电路笔记]非线性电路
  17. 程序员职业生涯11个阶段
  18. 程序设计入门C语言 --- 素数和
  19. 如何编写高质量的Java代码
  20. PB函数大全(超全,解析很全面)

热门文章

  1. C1任务01-修改游戏存档
  2. 深入理解java虚拟机 -- jVM高级特性与最佳实践
  3. 单片机 STM32F103C8T6 cubeMX HAL库 从环境到开发 正点原子工程移植 freeRTOS
  4. 转:通过他人完成任务的艺术 - 读《领导梯队》
  5. MybatisPlus实现多表联查
  6. Centos服务器加固安全的脚本
  7. 【AI创新者】小蚁首架张骏峰:让图像AI人尽可用
  8. Mysql学习篇之---Windows环境下安装 (修改密码)
  9. 撰写商业计划书的21条军规! (附: Airbnb 早年BP和Uber 路演PPT)
  10. 考研数学-排列组合(葛老师)-2020-03-14