Java 开发工具–Lombok介绍

来源:互联网 发布:美国硕士一年花费知乎 编辑:程序博客网 时间:2024/06/06 03:49

Java 开发工具–Lombok介绍

问题描述

在写POJO代码时,经常需要生成getter和setter方法,以及hashcode、tostring和equals等代码。感觉甚是麻烦,虽然有Eclipse或者intellij IDEA快捷键帮我们自动生成些代码,但感觉还是麻烦(其实就是懒)。
偶然中,得知Lombok Project,通过使用注解,可以消除冗余的java代码。
官网的介绍:Project Lombok makes java a spicier language by adding ‘handlers’ that know >how to build and compile simple, boilerplate-free, not-quite-java code.

如何使用

如果是maven管理的项目,通过引入dependency即可:

<dependency>    <groupId>org.projectlombok</groupId>    <artifactId>lombok</artifactId>    <version>1.16.12</version>    <scope>provided</scope></dependency>

Gradle项目的引入方式类似:

provided group: 'org.projectlombok', name: 'lombok', version: '1.16.18'

另外,在spring boot项目中,引入Lombok时没有必要指定和,因为 spring boot 已经帮我们自动配置好。

如何安装

先说IDEA,在IDEA中安装Lombok需要先安装插件,快捷键 Ctrl + Alt + S,然后选择 plugins——> browse repositories,搜索 Lombok,install即可,安装需要重启。
其次,Lombok是在编译时期,自动生成所需方法的,所以需要开启annotation processing;依旧是刚才的快捷键,可以搜索”annotation processing”,然后选择”Enable annotation processing”.
如果是Eclipse的话,官网下载最新的Lombok.jar,双击或者`java -jar lombok.jar在弹出的窗口,确认刚才 Lombok 扫描整个硬盘得到的Eclipse安装程序结果即可(Eclipse,MyEclipse,STS(Spring tool suite)),点击 Install/Update。

注解

刚才提到,Lombok是通过注解来减少编码的,那都提供哪些注解呢?
不完全统计:

@NonNull:标识对象是否为空,为空则抛出异常@Getter/@Setter:自动生成Getter/Setter方法@ToString:覆盖tostring方法,可以添加限制条件@EqualsAndHashCode:覆盖equal和hashCode方法,生成方法时只会使用类中的非静态和非transient成员变量@Data@Getter/@Setter, @ToString, @EqualAndHashCode@AllArgsConstructor等组合@Cleanup:用在变量前面,可以保证此变量代表的资源会被自动关闭,默认是调用资源的close()方法,如果该资源有其它关闭方法,可使用@Cleanup(“methodName”)来指定要调用的方法@NoArgsConstructor/@RequiredArgsConstructor /@AllArgsConstructor:第二个注解使用类中所有带有@NonNull注解的或带有final修饰的非静态成员变量生成对应的构造方法,@Log:类注解,可以省去从日志工厂生成日志对象这一步,直接进行日志记录,具体注解根据日志工具的不同而不同,同时,可以在注解中使用topic来指定生成log对象时的类名@Builder:关于build模式,可以参考《Effective  java》这本书@Value@SneakyThrows@Synchronized

实例代码判断

上面的注解简介太模糊?看看实例:

1 @Getter & @Setter & @ToString

public class Person {    private boolean employed;    private String name;    Person() {    }    public String say() {        return this.getName();    }    public String toString() {        return "Person(employed=" + this.isEmployed() + ", name=" + this.getName() + ")";    }    public boolean isEmployed() {        return this.employed;    }    public void setEmployed(boolean employed) {        this.employed = employed;    }    public String getName() {        return this.name;    }    protected void setName(String name) {        this.name = name;    }}

如果使用Lombok提供的注解:

@ToString class Person {    @Getter    @Setter    private boolean employed;    @Getter    @Setter(AccessLevel.PROTECTED)    private String name;    public String say() {        return getName();    }}

2. @Builder

这次先看看使用注解之前的java code:

@Builderpublic class BuilderExample {    private String name;    private int age;}

再看看其经过编译之后的java code:

import java.beans.ConstructorProperties;public class BuilderExample {    private String name;    private int age;    @ConstructorProperties({"name", "age"})    BuilderExample(String name, int age) {        this.name = name;        this.age = age;    }    public static BuilderExample.BuilderExampleBuilder builder() {        return new BuilderExample.BuilderExampleBuilder();    }    public static class BuilderExampleBuilder {        private String name;        private int age;        BuilderExampleBuilder() {        }        public BuilderExample.BuilderExampleBuilder name(String name) {            this.name = name;            return this;        }        public BuilderExample.BuilderExampleBuilder age(int age) {            this.age = age;            return this;        }        public BuilderExample build() {            return new BuilderExample(this.name, this.age);        }        public String toString() {            return "BuilderExample.BuilderExampleBuilder(name=" + this.name + ", age=" + this.age + ")";        }    }}

3. @Data

先看使用注解的类:

@Datapublic class User {    private Integer id;    private String password;}

编译之后的类长这样:

public class User {    private Integer id;    private String password;    public User() {    }    public Integer getId() {        return this.id;    }    public String getPassword() {        return this.password;    }    public void setId(Integer id) {        this.id = id;    }    public void setPassword(String password) {        this.password = password;    }    public boolean equals(Object o) {        if (o == this) {            return true;        } else if (!(o instanceof User)) {            return false;        } else {            User other = (User)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;                }                Object this$password = this.getPassword();                Object other$password = other.getPassword();                if (this$password == null) {                    if (other$password != null) {                        return false;                    }                } else if (!this$password.equals(other$password)) {                    return false;                }                return true;            }        }    }    protected boolean canEqual(Object other) {        return other instanceof User;    }    public int hashCode() {        int PRIME = true;        int result = 1;        Object $id = this.getId();        int result = result * 59 + ($id == null ? 43 : $id.hashCode());        Object $password = this.getPassword();        result = result * 59 + ($password == null ? 43 : $password.hashCode());        return result;    }    public String toString() {        return "User(id=" + this.getId() + ", password=" + this.getPassword() + ")";    }}

更多注解的用法,感兴趣的话,请参考官网。

Lombok原理

采用JSR269所提出的插入式注解处理(Pluggable Annotation Processing),并结合动态代码生成技术所开发的。如下图所示:
这里写图片描述
图示为 javac 的编译过程,java文件首先通过进行解析构建出一个AST,然后执行注解处理,最后经过分析优化生成二进制的.class文件。
Annotation Processing 是在解析和生成之间的一个步骤。
这里写图片描述
上图是 Lombok 处理流程,在Javac 解析成抽象语法树之后(AST),Lombok 根据自己的注解处理器,动态的修改 AST,增加新的节点(所谓代码),最终通过分析和生成字节码。

Lombok缺点

这么好的工具,那可以应用到生产环境吗?真不一定,Lombok 注解的引入一定程度上会造成源码的可读性(不是所有人都了解其使用)和完整性,而且生成环境使用,不一定还会遇到什么坑,看看其代码托管GitHub的issue就知道。
不过反过来一想,issue 开得多,不正说明其应用还是很广泛的?

参考

基本实现原理
jdk-compilation-overview

原创粉丝点击