跳转至

关于Lombok

约 660 个字 133 行代码 预计阅读时间 4 分钟

Lombok 是一个 Java 注解库,它通过在编译期自动生成样板代码,帮助开发者减少 getter、setter、构造方法、toString() 等重复代码的编写。使用 Lombok 时需要保证 IDE 正确安装插件并开启注解处理功能。

依赖引入

在 Maven 项目中,Lombok 通常使用 provided 作用域,表示只在编译期使用,不会被打包到最终的 JAR 中。下面的示例使用的是当前较新的稳定版本 1.18.36

XML
 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
<properties>
    <java.version>17</java.version>
    <lombok.version>1.18.36</lombok.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.13.0</version>
            <configuration>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>${lombok.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

如果使用 Spring Boot,通常可以直接引入依赖而无需显式指定版本:

XML
1
2
3
4
5
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <scope>provided</scope>
</dependency>

常用注解

注解 作用
@Data 组合注解,包含 @Getter@Setter@ToString@EqualsAndHashCode@RequiredArgsConstructor
@Getter / @Setter 自动生成 getter / setter 方法
@NoArgsConstructor 生成无参构造方法
@AllArgsConstructor 生成全参构造方法
@RequiredArgsConstructor final 字段生成构造方法,常用于 Spring 依赖注入
@ToString 生成 toString() 方法
@EqualsAndHashCode 生成 equals()hashCode() 方法
@Slf4j 自动生成 SLF4J 日志对象 log
@Log4j2 自动生成 Log4j2 日志对象
@Builder 生成 Builder 模式代码
@Value 生成不可变对象,字段默认为 final
@NonNull 标记字段或参数不能为 null
@SneakyThrows 将受检异常转换为非受检异常抛出
@Accessors(chain = true) 开启链式 setter 调用

实体类简化示例

使用 @Data 可以大幅减少实体类中的样板代码:

Java
1
2
3
4
5
6
7
8
import lombok.Data;

@Data
public class User {
    private Long id;
    private String username;
    private String email;
}

上面的代码编译后,会自动生成 getId()setId(...)getUsername()setUsername(...)getEmail()setEmail(...)toString()equals()hashCode() 以及一个包含 final 字段的构造方法(如果存在 final 字段)。

构造方法相关注解

无参与全参构造

Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Long id;
    private String username;
}

final 字段生成构造方法

在 Spring 项目中,常用 @RequiredArgsConstructor 替代 @Autowired 字段注入:

Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {

    private final UserMapper userMapper;

    public void queryById(Long id) {
        log.info("查询用户:{}", id);
        userMapper.selectById(id);
    }
}

@RequiredArgsConstructor@AllArgsConstructor的区别

@RequiredArgsConstructor会为所有被final或者@NonNull修饰的字段提供一个构造器,其他没有被修饰的则不会提供构造器,而@AllArgsConstructor不考虑是否有修饰都会为所有字段提供构造器。例如:

Java
1
2
3
4
5
6
7
@RequiredArgsConstructor
public class User {
    private final Long id;
    @NonNull
    private String name;
    private int age;        // 普通字段,不进构造器
}

生成的构造器如下:

Java
1
2
3
4
public User(Long id, String name) {
    this.id = id;
    this.name = name;
}

日志注解

使用 @Slf4j 后,可以直接在代码中使用 log 对象:

Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class LogDemo {
    public void doSomething() {
        log.info("执行 doSomething");
        log.warn("警告信息");
        log.error("错误信息");
    }
}

Tip

使用 @Slf4j 时,项目中需要有 SLF4J 的实现依赖,例如 logback-classiclog4j-slf4j-impl

构建器模式

使用 @Builder 可以快速生成 Builder 模式代码:

Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Product {
    private Long id;
    private String name;
    private Double price;
}

使用方式如下:

Java
1
2
3
4
5
Product product = Product.builder()
        .id(1L)
        .name("iPhone")
        .price(5999.0)
        .build();

其他实用注解

@Value

用于创建不可变对象,所有字段默认是 final,并且只生成 getter,不生成 setter:

Java
1
2
3
4
5
6
7
import lombok.Value;

@Value
public class Config {
    String host;
    int port;
}

@NonNull

标记字段或参数不能为 null,Lombok 会在对应的方法中加入非空校验,一旦传 null 直接抛 NullPointerException

Java
1
2
3
4
5
6
7
import lombok.NonNull;

public class UserService {
    public void updateName(@NonNull String name) {
        // ...
    }
}

@SneakyThrows

用于在不需要显式 try...catchthrows 的情况下抛出受检异常:

Java
1
2
3
4
5
6
7
8
9
import lombok.SneakyThrows;

public class Demo {
    @SneakyThrows
    public void readFile() {
        // InterruptedException 等受检异常可以直接抛出
        Thread.sleep(1000);
    }
}