Lombok

作用:帮使用者提高编码效率,减少重复与冗余的代码

原理:ASM 动态修改class文件


配置

maven

依赖

1
2
3
4
5
 <dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.8</version>
</dependency>

编译

1
2
3
4
5
6
7
8
9
    <build>
<plugins>
<plugin>
<groupId>org.projectlombok</groupId>
<artifactId>lombok-maven-plugin</artifactId>
<version>1.16.6.1</version>
</plugin>
</plugins>
</build>

idea

  • 安装插件

常用注解:

java bean相关

@Setter

  • 功能

    生成setter方法

  • 源码
    1
    2
    3
    4
    5
    6
    @Setter
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

package xyz.mrwood.study.lombok;

public class LombokDemo {
private Integer id;
private String name;

public LombokDemo() {
}

public void setId(Integer id) {
this.id = id;
}

public void setName(String name) {
this.name = name;
}
}

@Getter

  • 功能

    生成getter方法

  • 源码
    1
    2
    3
    4
    5
    6
    @Getter
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package xyz.mrwood.study.lombok;

public class LombokDemo {
private Integer id;
private String name;

public LombokDemo() {
}

public Integer getId() {
return this.id;
}

public String getName() {
return this.name;
}
}

@ToString

  • 功能

    生成toString方法

  • 源码

    1
    2
    3
    4
    5
    6
    @ToString
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer id;
    private String name;

    public LombokDemo() {
    }

    public String toString() {
    return "LombokDemo(id=" + this.id + ", name=" + this.name + ")";
    }
    }

@Getter(lazy = true)

  • 功能

    懒加载属性

  • 注意:

    这个与上面@Getter不同,那个是修饰在类上的,也可以修饰在属性上。如果有lazy=true只能修饰在属性,并且还要是private final修饰,限制很大

  • 编码

    1
    2
    3
    4
    5
    public class LombokDemo {

    @Getter(lazy = true) private final List<Integer> ids = Arrays.asList(1, 2, 3, 4);
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package xyz.mrwood.study.lombok;

    import java.util.Arrays;
    import java.util.List;
    import java.util.concurrent.atomic.AtomicReference;

    public class LombokDemo {
    private final AtomicReference<Object> ids = new AtomicReference();
    private String name;

    public LombokDemo() {
    }

    public List<Integer> getIds() {
    Object value = this.ids.get();
    if(value == null) {
    AtomicReference var2 = this.ids;
    synchronized(this.ids) {
    value = this.ids.get();
    if(value == null) {
    List actualValue = Arrays.asList(new Integer[]{Integer.valueOf(1), Integer.valueOf(2), Integer.valueOf(3), Integer.valueOf(4)});
    value = actualValue == null?this.ids:actualValue;
    this.ids.set(value);
    }
    }
    }

    return (List)((List)(value == this.ids?null:value));
    }
    }

@EqualsAndHashCode

  • 功能

    生成equals方法与hashCode方法

  • 源码
1
2
3
4
5
6
7
@EqualsAndHashCode
public class LombokDemo {

private Integer id;
private String name;
}

  • 编译后
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package xyz.mrwood.study.lombok;

public class LombokDemo {
private Integer id;
private String name;

public LombokDemo() {
}

public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof LombokDemo)) {
return false;
} else {
LombokDemo other = (LombokDemo)o;
if(!other.canEqual(this)) {
return false;
} else {
Integer this$id = this.id;
Integer other$id = other.id;
if(this$id == null) {
if(other$id != null) {
return false;
}
} else if(!this$id.equals(other$id)) {
return false;
}

String this$name = this.name;
String other$name = other.name;
if(this$name == null) {
if(other$name != null) {
return false;
}
} else if(!this$name.equals(other$name)) {
return false;
}

return true;
}
}
}

protected boolean canEqual(Object other) {
return other instanceof LombokDemo;
}

public int hashCode() {
boolean PRIME = true;
byte result = 1;
Integer $id = this.id;
int result1 = result * 59 + ($id == null?43:$id.hashCode());
String $name = this.name;
result1 = result1 * 59 + ($name == null?43:$name.hashCode());
return result1;
}
}

@NoAragsConstructor

  • 功能

    添加一个无参构造函数

  • 注意

    这个注解在没有其它有参构造函数的情况下使用意义不大,因为在这种情况下java默认会添加一个无参构造函数

  • 源码

    1
    2
    3
    4
    5
    6
    @NoArgsConstructor
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer id;
    private String name;

    public LombokDemo() {
    }
    }

@AllArgsConstructor

  • 功能

    添加一个所有参数的构造函数

  • 源码

    1
    2
    3
    4
    5
    6
    @AllArgsConstructor
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package xyz.mrwood.study.lombok;

    import java.beans.ConstructorProperties;

    public class LombokDemo {
    private Integer id;
    private String name;

    @ConstructorProperties({"id", "name"})
    public LombokDemo(Integer id, String name) {
    this.id = id;
    this.name = name;
    }
    }

@RequiredArgsConstructor

  • 功能

    生成一个包含必填参数的构造函数

  • 注意

    要与@NonNull 搭配使用,该注解修饰的属性就是必填参数

  • 源码

    1
    2
    3
    4
    5
    6
    @RequiredArgsConstructor
    public class LombokDemo {

    @NonNull private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package xyz.mrwood.study.lombok;

    import java.beans.ConstructorProperties;
    import lombok.NonNull;

    public class LombokDemo {
    @NonNull
    private Integer id;
    private String name;

    @ConstructorProperties({"id"})
    public LombokDemo(@NonNull Integer id) {
    if(id == null) {
    throw new NullPointerException("id");
    } else {
    this.id = id;
    }
    }
    }

@Date

  • 功能

    这是一个综合注解了,等于同时使用

    @Getter, @Setter, @ToString, @EqualsAndHashCode,@RequiredArgsConstructor

  • 源码

    1
    2
    3
    4
    5
    6
    @Data
    public class LombokDemo {

    @NonNull private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer id;
    private String name;

    public LombokDemo() {
    }

    public Integer getId() {
    return this.id;
    }

    public String getName() {
    return this.name;
    }

    public void setId(Integer id) {
    this.id = id;
    }

    public void setName(String name) {
    this.name = name;
    }

    public boolean equals(Object o) {
    if(o == this) {
    return true;
    } else if(!(o instanceof LombokDemo)) {
    return false;
    } else {
    LombokDemo other = (LombokDemo)o;
    if(!other.canEqual(this)) {
    return false;
    } else {
    Integer this$id = this.getId();
    Integer other$id = other.getId();
    if(this$id == null) {
    if(other$id != null) {
    return false;
    }
    } else if(!this$id.equals(other$id)) {
    return false;
    }

    String this$name = this.getName();
    String other$name = other.getName();
    if(this$name == null) {
    if(other$name != null) {
    return false;
    }
    } else if(!this$name.equals(other$name)) {
    return false;
    }

    return true;
    }
    }
    }

    protected boolean canEqual(Object other) {
    return other instanceof LombokDemo;
    }

    public int hashCode() {
    boolean PRIME = true;
    byte result = 1;
    Integer $id = this.getId();
    int result1 = result * 59 + ($id == null?43:$id.hashCode());
    String $name = this.getName();
    result1 = result1 * 59 + ($name == null?43:$name.hashCode());
    return result1;
    }

    public String toString() {
    return "LombokDemo(id=" + this.getId() + ", name=" + this.getName() + ")";
    }
    }

@Value

  • 功能

    不可变类的@Date, 他会默认给属性加上final

  • 源码

    1
    2
    3
    4
    5
    6
    @Value
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    package xyz.mrwood.study.lombok;

    import java.beans.ConstructorProperties;

    public final class LombokDemo {
    private final Integer id;
    private final String name;

    @ConstructorProperties({"id", "name"})
    public LombokDemo(Integer id, String name) {
    this.id = id;
    this.name = name;
    }

    public Integer getId() {
    return this.id;
    }

    public String getName() {
    return this.name;
    }

    public boolean equals(Object o) {
    if(o == this) {
    return true;
    } else if(!(o instanceof LombokDemo)) {
    return false;
    } else {
    LombokDemo other = (LombokDemo)o;
    Integer this$id = this.getId();
    Integer other$id = other.getId();
    if(this$id == null) {
    if(other$id != null) {
    return false;
    }
    } else if(!this$id.equals(other$id)) {
    return false;
    }

    String this$name = this.getName();
    String other$name = other.getName();
    if(this$name == null) {
    if(other$name != null) {
    return false;
    }
    } else if(!this$name.equals(other$name)) {
    return false;
    }

    return true;
    }
    }

    public int hashCode() {
    boolean PRIME = true;
    byte result = 1;
    Integer $id = this.getId();
    int result1 = result * 59 + ($id == null?43:$id.hashCode());
    String $name = this.getName();
    result1 = result1 * 59 + ($name == null?43:$name.hashCode());
    return result1;
    }

    public String toString() {
    return "LombokDemo(id=" + this.getId() + ", name=" + this.getName() + ")";
    }
    }

@Accessors

  • 功能

    这个注解要搭配@Getter与@Setter使用,用来修改默认的setter与getter方法的形式

  • 注意

    @Accessors有三个参数可以使用

    1. chain 链式的形式
    2. fluent 流式的形式
    3. prefix 生成指定前缀的属性的getter与setter方法,并且生成的getter与setter方法时会去除前缀
  • 源码 chain = true

    1
    2
    3
    4
    5
    6
    7
    8
    @Accessors(chain = true)
    @Setter
    @Getter
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后 chain = true

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer id;
    private String name;

    public LombokDemo() {
    }

    public LombokDemo setId(Integer id) {
    this.id = id;
    return this;
    }

    public LombokDemo setName(String name) {
    this.name = name;
    return this;
    }

    public Integer getId() {
    return this.id;
    }

    public String getName() {
    return this.name;
    }
    }

  • 源码 fluent = true

    1
    2
    3
    4
    5
    6
    7
    8
    @Accessors(fluent = true)
    @Setter
    @Getter
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后 fluent = true

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer id;
    private String name;

    public LombokDemo() {
    }

    public LombokDemo id(Integer id) {
    this.id = id;
    return this;
    }

    public LombokDemo name(String name) {
    this.name = name;
    return this;
    }

    public Integer id() {
    return this.id;
    }

    public String name() {
    return this.name;
    }
    }
  • 源码 prefix = "xxx"

    1
    2
    3
    4
    5
    6
    7
    8
    @Accessors(prefix = "xxx")
    @Setter
    @Getter
    public class LombokDemo {

    private Integer xxxId;
    private String name;
    }
  • 编译后 prefix = "xxx"

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer xxxId;
    private String name;

    public LombokDemo() {
    }

    public void setId(Integer xxxId) {
    this.xxxId = xxxId;
    }

    public Integer getId() {
    return this.xxxId;
    }
    }


其它注解:

日志相关

@Log4j

  • 源码

    1
    2
    3
    4
    5
    6
    @Log4j
    public class LombokDemo {

    private Integer xxxId;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package xyz.mrwood.study.lombok;

    import org.apache.log4j.Logger;

    public class LombokDemo {
    private static final Logger log = Logger.getLogger(LombokDemo.class);
    private Integer xxxId;
    private String name;

    public LombokDemo() {
    }
    }

@CommonsLog

  • 源码

    1
    2
    3
    4
    5
    6
    @CommonsLog
    public class LombokDemo {

    private Integer xxxId;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package xyz.mrwood.study.lombok;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;

    public class LombokDemo {
    private static final Log log = LogFactory.getLog(LombokDemo.class);
    private Integer xxxId;
    private String name;

    public LombokDemo() {
    }
    }

@Log

  • 源码

    1
    2
    3
    4
    5
    6
    @Log
    public class LombokDemo {

    private Integer xxxId;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    package xyz.mrwood.study.lombok;

    import java.util.logging.Logger;

    public class LombokDemo {
    private static final Logger log = Logger.getLogger(LombokDemo.class.getName());
    private Integer xxxId;
    private String name;

    public LombokDemo() {
    }
    }

@Log4j2

  • 源码

    1
    2
    3
    4
    5
    6
    @Log4j2
    public class LombokDemo {

    private Integer xxxId;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package xyz.mrwood.study.lombok;

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;

    public class LombokDemo {
    private static final Logger log = LogManager.getLogger(LombokDemo.class);
    private Integer xxxId;
    private String name;

    public LombokDemo() {
    }
    }

@Slf4j

  • 源码

    1
    2
    3
    4
    5
    6
    @Slf4j
    public class LombokDemo {

    private Integer xxxId;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    package xyz.mrwood.study.lombok;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    public class LombokDemo {
    private static final Logger log = LoggerFactory.getLogger(LombokDemo.class);
    private Integer xxxId;
    private String name;

    public LombokDemo() {
    }
    }

设计模式相关

@Builder

  • 功能

    通过建造者模块来生成bean

  • 源码

    1
    2
    3
    4
    5
    6
    @Builder
    public class LombokDemo {

    private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer id;
    private String name;

    LombokDemo(Integer id, String name) {
    this.id = id;
    this.name = name;
    }

    public static LombokDemo.LombokDemoBuilder builder() {
    return new LombokDemo.LombokDemoBuilder();
    }

    public static class LombokDemoBuilder {
    private Integer id;
    private String name;

    LombokDemoBuilder() {
    }

    public LombokDemo.LombokDemoBuilder id(Integer id) {
    this.id = id;
    return this;
    }

    public LombokDemo.LombokDemoBuilder name(String name) {
    this.name = name;
    return this;
    }

    public LombokDemo build() {
    return new LombokDemo(this.id, this.name);
    }

    public String toString() {
    return "LombokDemo.LombokDemoBuilder(id=" + this.id + ", name=" + this.name + ")";
    }
    }
    }

@Delegate

  • 功能

    @Delegate注释的属性,会把这个属性对象的公有非静态方法合到当前类

  • 注意

    公共 非静态方法

  • 源码

    1
    2
    3
    4
    5
    6
    public class LombokDemo {

    @Delegate
    private Integer id;
    private String name;
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    package xyz.mrwood.study.lombok;

    public class LombokDemo {
    private Integer id;
    private String name;

    public LombokDemo() {
    }

    public byte byteValue() {
    return this.id.byteValue();
    }

    public short shortValue() {
    return this.id.shortValue();
    }

    public int intValue() {
    return this.id.intValue();
    }

    public long longValue() {
    return this.id.longValue();
    }

    public float floatValue() {
    return this.id.floatValue();
    }

    public double doubleValue() {
    return this.id.doubleValue();
    }

    public int compareTo(Integer arg0) {
    return this.id.compareTo(arg0);
    }
    }

工具相关

@Cleanup

  • 功能

    关闭流

  • 注意

    关闭流的方式有点怪异,而且没有在finally里面关闭,如果出现异常的就不会关闭了

  • 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class LombokDemo {

    public void test() throws IOException {

    @Cleanup InputStream inputStream = new FileInputStream("xxx.txt");

    }

    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package xyz.mrwood.study.lombok;

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.util.Collections;

    public class LombokDemo {
    public LombokDemo() {
    }

    public void test() throws IOException {
    FileInputStream inputStream = new FileInputStream("xxx.txt");
    if(Collections.singletonList(inputStream).get(0) != null) {
    inputStream.close();
    }

    }
    }

@Synchronized

  • 功能

    给方法加一个同步块

  • 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class LombokDemo {

    @Synchronized
    public void test() throws IOException {

    System.out.println("test");

    }

    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    package xyz.mrwood.study.lombok;

    import java.io.IOException;

    public class LombokDemo {
    private final Object $lock = new Object[0];

    public LombokDemo() {
    }

    public void test() throws IOException {
    Object var1 = this.$lock;
    synchronized(this.$lock) {
    System.out.println("test");
    }
    }
    }

@SneakyThrows

  • 功能

    忽略异常

  • 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class LombokDemo {

    @SneakyThrows
    public void test() {

    String s = new String("test".getBytes(), "utf-8");

    }

    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    package xyz.mrwood.study.lombok;

    import java.io.IOException;

    public class LombokDemo {
    private final Object $lock = new Object[0];

    public LombokDemo() {
    }

    public void test() throws IOException {
    Object var1 = this.$lock;
    synchronized(this.$lock) {
    System.out.println("test");
    }
    }
    }

@NonNull

  • 功能

    设置不能为空的参数

  • 源码

    1
    2
    3
    4
    5
    6
    public class LombokDemo {

    public void test(@NonNull String val) {

    }
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package xyz.mrwood.study.lombok;

    import lombok.NonNull;

    public class LombokDemo {
    public LombokDemo() {
    }

    public void test(@NonNull String val) {
    if(val == null) {
    throw new NullPointerException("val");
    }
    }
    }

    @UtilityClass

  • 功能

    把普通类转为工具类

  • 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @UtilityClass
    public class LombokDemo {

    private Integer id = 1;
    private String name = "kiwi";

    public void util(){

    System.out.println("xxx");
    }
    }
  • 编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    package xyz.mrwood.study.lombok;

    public final class LombokDemo {
    private static Integer id = Integer.valueOf(1);
    private static String name = "kiwi";

    public static void util() {
    System.out.println("xxx");
    }

    private LombokDemo() {
    throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }
    }

本文地址 https://blog.coder4j.cn/posts/488c3b78/