Lombok 依赖和插件介绍

2021-09-25 0 By admin

在 Java 项目开发过程中,可能存在一些不友好、重复性的代码,为了保证代码的简洁性,可以使用依赖辅助的依赖包和插件。
Lombok 就是这样一个工具,IDEA 2020开发 IDE 最后一个版本发布了,已经内置了Lombok插件;而 SpringBoot 2.1.x 之后的版本也在Starter中也内置了Lombok依赖。

Lombok是一款Java代码功能增强库,在Github上已有9.8k+Star。它会自动集成到你的编辑器和构建工具中,从而使你的Java代码更加生动有趣。通过Lombok的注解,你可以不用再写getter、setter、equals等方法,Lombok将在编译时为你自动生成。

一、Lombok 集成

1.1、IDEA 安装 Lombok 插件

首先我们需要在IDEA中安装好Lombok插件,如果你使用的是最新版IDEA 2020.3,则Lombok插件已经内置,无需安装。
安装过程:打开IDEA的Setting –> 选择Plugins选项 –> 选择Browse repositories –> 搜索lombok –> 点击安装 –> 安装完成重启IDEA –> 安装成功

1.2、SpringBoot 添加 Lombok 依赖

在项目的pom.xml文件中添加Lombok依赖,SpringBoot 2.1.x版本后无需指定Lombok版本,SpringBoot在spring-boot-dependencies中已经内置。

<!--lombok依赖-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

二、Lombok 注解介绍

Lombok中有很多注解,这些注解使得我们可以更加方便的编写Java代码,下面介绍下这些注解的使用。

2.1、val 声明局部变量类型

使用val注解可以取代任意类型作为局部变量,这样我们就不用写复杂的ArrayList和Map.Entry类型了,具体例子如下。

public class ValExample {
    public static void example() {
        //val代替ArrayList<String>和String类型
        val example = new ArrayList<String>();
        example.add("Hello World!");
        val foo = example.get(0);
        System.out.println(foo.toLowerCase());
    }
    public static void example2() {
        //val代替Map.Entry<Integer,String>类型
        val map = new HashMap<Integer, String>();
        map.put(0, "zero");
        map.put(5, "five");
        for (val entry : map.entrySet()) {
            System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
        }
    }
    public static void main(String[] args) {
        example();
        example2();
    }
}

当我们使用了val注解后,Lombok会从局部变量的初始化表达式推断出具体类型,编译后会生成如下代码。

public class ValExample {
    public ValExample() {
    }
    public static void example() {
        ArrayList<String> example = new ArrayList();
        example.add("Hello World!");
        String foo = (String)example.get(0);
        System.out.println(foo.toLowerCase());
    }
    public static void example2() {
        HashMap<Integer, String> map = new HashMap();
        map.put(0, "zero");
        map.put(5, "five");
        Iterator var1 = map.entrySet().iterator();
        while(var1.hasNext()) {
            Entry<Integer, String> entry = (Entry)var1.next();
            System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
        }
    }
}

2.2、@NonNull 非空判断

在方法上使用@NonNull注解可以做非空判断,如果传入空值的话会直接抛出NullPointerException。

public class NonNullExample {
    private String name;
    public NonNullExample(@NonNull String name){
        this.name = name;
    }
    public static void main(String[] args) {
        new NonNullExample("test");
        //会抛出NullPointerException
        new NonNullExample(null);
    }
}

编译后会在构造器中添加非空判断,具体代码如下。

public class NonNullExample {
    private String name;
    public NonNullExample(@NonNull String name) {
        if (name == null) {
            throw new NullPointerException("name is marked non-null but is null");
        } else {
            this.name = name;
        }
    }
    public static void main(String[] args) {
        new NonNullExample("test");
        new NonNullExample((String)null);
    }
}

2.3、@Cleanup 关闭资源

当我们在Java中使用资源时,不可避免地需要在使用后关闭资源。使用@Cleanup注解可以自动关闭资源。

public class CleanupExample {
    public static void main(String[] args) throws IOException {
        String inStr = "Hello World!";
        //使用输入输出流自动关闭,无需编写try catch和调用close()方法
        @Cleanup ByteArrayInputStream in = new ByteArrayInputStream(inStr.getBytes("UTF-8"));
        @Cleanup ByteArrayOutputStream out = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        while (true) {
            int r = in.read(b);
            if (r == -1) break;
            out.write(b, 0, r);
        }
        String outStr = out.toString("UTF-8");
        System.out.println(outStr);
    }
}

编译后Lombok会生成如下代码:

public class CleanupExample {
    public CleanupExample() {
    }
    public static void main(String[] args) throws IOException {
        String inStr = "Hello World!";
        ByteArrayInputStream in = new ByteArrayInputStream(inStr.getBytes("UTF-8"));
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            try {
                byte[] b = new byte[1024];
                while(true) {
                    int r = in.read(b);
                    if (r == -1) {
                        String outStr = out.toString("UTF-8");
                        System.out.println(outStr);
                        return;
                    }
                    out.write(b, 0, r);
                }
            } finally {
                if (Collections.singletonList(out).get(0) != null) {
                    out.close();
                }
            }
        } finally {
            if (Collections.singletonList(in).get(0) != null) {
                in.close();
            }
        }
    }
}

2.4、@Getter/@Setter 类属性方法

有了@Getter/@Setter注解,我们再也不用编写getter/setter方法了。试想下之前即使我们使用IDEA自动生成getter/setter方法,如果类属性的类型和名称改了,又要重新生成getter/setter方法也是一件很麻烦的事情。

public class GetterSetterExample {
    @Getter
    @Setter
    private String name;
    @Getter
    @Setter(AccessLevel.PROTECTED)
    private Integer age;

    public static void main(String[] args) {
        GetterSetterExample example = new GetterSetterExample();
        example.setName("test");
        example.setAge(20);
        System.out.printf("name:%s age:%d",example.getName(),example.getAge());
    }
}

编译后Lombok会生成如下代码。

public class GetterSetterExample {
    private String name;
    private Integer age;
    public GetterSetterExample() {
    }
    public String getName() {
        return this.name;
    }
    public void setName(final String name) {
        this.name = name;
    }
    public Integer getAge() {
        return this.age;
    }
    protected void setAge(final Integer age) {
        this.age = age;
    }
}

2.5、@ToString 输出类所有属性

把所有类属性都编写到toString方法中方便打印日志,是一件多么枯燥无味的事情。
使用@ToString注解可以自动生成toString方法,默认会包含所有类属性,使用@ToString.Exclude注解可以排除属性的生成。

@ToString
public class ToStringExample {
    @ToString.Exclude
    private Long id;
    private String name;
    private Integer age;
    public ToStringExample(Long id,String name,Integer age){
        this.id =id;
        this.name = name;
        this.age = age;
    }
    public static void main(String[] args) {
        ToStringExample example = new ToStringExample(1L,"test",20);
        //自动实现toString方法,输出ToStringExample(name=test, age=20)
        System.out.println(example);
    }
}

编译后Lombok会生成如下代码。

public class ToStringExample {
    private Long id;
    private String name;
    private Integer age;
    public ToStringExample(Long id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    public String toString() {
        return "ToStringExample(name=" + this.name + ", age=" + this.age + ")";
    }
}