Lombok初遇

原理

Lombok主要作用于编译阶段,从JDK1.6开始,javac可以处理遵循《JSR 269 Pluggable Annotation Processing API》规范的注解,Lombok的注解处理器就可以在编译阶段被调用。

大致流程如下:

  1. javac对源代码进行分析,生成一棵抽象语法树(AST)
  2. javac编译过程中调用遵循JSR 269规范的Lombok注解处理器
  3. Lombok注解处理器获取到需要处理的AST
  4. Lombok注解处理器找到Lombok注解,生成对应的代码,修改对应的AST,生成新的AST
  5. javac使用新的AST生成字节码文件

安装使用

Lombok需要安装,使用命令行:

java -jar lombok.jar

然后有图形界,可以看到在自动查找IDE,这种方式主要是针对Eclipse。

lombok安装

如果不行,就eclipse.ini手动添加:

; 在启动类路径中添加的Lombok
-Xbootclasspath/D:lombok.jar
; 设置代理
-javaagent:lombok.jar

如果是IDEA,那么就直接通过Marketplace安装。

lombok
安装之后,有依赖Lombok的项目就会自动配置,如果没有就需要手动配置一下。

annotation processing

maven配置

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.16</version>
    <scope>provided</scope>
</dependency>
<repositories>
    <repository>
        <id>projectlombok.org</id>
        <url>http://projectlombok.org/mavenrepo</url>
    </repository>
</repositories>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>1.18.16</version>
                    </path>                         
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>

常用注解

注解注解目标说明
@Log生成日志变量,@Log、@Slf4j、@Log4j、@Log4j2等
@Data大礼包,包含@ToString、@EqualsAndHashCode、@Getter、@Setter、@RequiredArgsConstructor
@Getter类或成员变量生成getter方法
@Setter类或成员变量生成setter方法
@NonNull成员变量和参数变量参数不能为空,否则抛出空指针异常
@Builder将类转变为建造者模式
@Cleanup变量自动关闭资源,实现java.io.Closeable接口才有效
@ToString覆盖toString()方法,of包含字段、exclude排除属性排除字段
@SneakyThrows方法捕捉并抛出受检异常
@Synchronized方法和Java自己的synchronized基本一样,实际就是通过synchronized关键字来实现
@EqualsAndHashCode覆盖equals和hashCode方法
@NoArgsConstructor生成无参构造函数
@AllArgsConstructor生成全参构造函数
@RequiredArgsConstructor生成包含final和@NonNull注解的成员变量的构造函数

实例说明

一个简单的例子,可以看一下,Lombok注解器对不同的注解都生成了什么样的代码。

import lombok.Builder;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;

import java.sql.Date;
import java.sql.SQLDataException;

@Data
@Slf4j
@Builder
public class User {

    private Integer id;
    private String name;
    private Date birthday;

    @Synchronized
    public void doSomethingA(){

    }

    @SneakyThrows
    public void doSomethingB(){
        throw new SQLDataException();
    }
}

Lombok处理后的代码:

import java.sql.Date;
import java.sql.SQLDataException;

public class User {
    @java.lang.SuppressWarnings("all")
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(User.class);
    @java.lang.SuppressWarnings("all")
    private final java.lang.Object $lock = new java.lang.Object[0];
    private Integer id;
    private String name;
    private Date birthday;

    public void doSomethingA() {
        synchronized (this.$lock) {
        }
    }

    public void doSomethingB() {
        try {
            throw new SQLDataException();
        } catch (final java.lang.Throwable $ex) {
            throw lombok.Lombok.sneakyThrow($ex);
        }
    }

    @java.lang.SuppressWarnings("all")
    User(final Integer id, final String name, final Date birthday) {
        this.id = id;
        this.name = name;
        this.birthday = birthday;
    }


    @java.lang.SuppressWarnings("all")
    public static class UserBuilder {
        @java.lang.SuppressWarnings("all")
        private Integer id;
        @java.lang.SuppressWarnings("all")
        private String name;
        @java.lang.SuppressWarnings("all")
        private Date birthday;

        @java.lang.SuppressWarnings("all")
        UserBuilder() {
        }

        @java.lang.SuppressWarnings("all")
        public User.UserBuilder id(final Integer id) {
            this.id = id;
            return this;
        }

        @java.lang.SuppressWarnings("all")
        public User.UserBuilder name(final String name) {
            this.name = name;
            return this;
        }

        @java.lang.SuppressWarnings("all")
        public User.UserBuilder birthday(final Date birthday) {
            this.birthday = birthday;
            return this;
        }

        @java.lang.SuppressWarnings("all")
        public User build() {
            return new User(this.id, this.name, this.birthday);
        }

        @java.lang.Override
        @java.lang.SuppressWarnings("all")
        public java.lang.String toString() {
            return "User.UserBuilder(id=" + this.id + ", name=" + this.name + ", birthday=" + this.birthday + ")";
        }
    }

    @java.lang.SuppressWarnings("all")
    public static User.UserBuilder builder() {
        return new User.UserBuilder();
    }

    @java.lang.SuppressWarnings("all")
    public Integer getId() {
        return this.id;
    }

    @java.lang.SuppressWarnings("all")
    public String getName() {
        return this.name;
    }

    @java.lang.SuppressWarnings("all")
    public Date getBirthday() {
        return this.birthday;
    }

    @java.lang.SuppressWarnings("all")
    public void setId(final Integer id) {
        this.id = id;
    }

    @java.lang.SuppressWarnings("all")
    public void setName(final String name) {
        this.name = name;
    }

    @java.lang.SuppressWarnings("all")
    public void setBirthday(final Date birthday) {
        this.birthday = birthday;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    public boolean equals(final java.lang.Object o) {
        if (o == this) return true;
        if (!(o instanceof User)) return false;
        final User other = (User) o;
        if (!other.canEqual((java.lang.Object) this)) return false;
        final java.lang.Object this$id = this.getId();
        final java.lang.Object other$id = other.getId();
        if (this$id == null ? other$id != null : !this$id.equals(other$id)) return false;
        final java.lang.Object this$name = this.getName();
        final java.lang.Object other$name = other.getName();
        if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
        final java.lang.Object this$birthday = this.getBirthday();
        final java.lang.Object other$birthday = other.getBirthday();
        if (this$birthday == null ? other$birthday != null : !this$birthday.equals(other$birthday)) return false;
        return true;
    }

    @java.lang.SuppressWarnings("all")
    protected boolean canEqual(final java.lang.Object other) {
        return other instanceof User;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    public int hashCode() {
        final int PRIME = 59;
        int result = 1;
        final java.lang.Object $id = this.getId();
        result = result * PRIME + ($id == null ? 43 : $id.hashCode());
        final java.lang.Object $name = this.getName();
        result = result * PRIME + ($name == null ? 43 : $name.hashCode());
        final java.lang.Object $birthday = this.getBirthday();
        result = result * PRIME + ($birthday == null ? 43 : $birthday.hashCode());
        return result;
    }

    @java.lang.Override
    @java.lang.SuppressWarnings("all")
    public java.lang.String toString() {
        return "User(id=" + this.getId() + ", name=" + this.getName() + ", birthday=" + this.getBirthday() + ")";
    }
}

如果想要看更多注解生成的代码,可以自己动手实验一下,使用下面的delombok获取Lombok处理之后的Java源代码。

delombok

通过delombok可以查看编译之后的Java源文件是咋样的。

# 编译整个src目录
java -jar lombok.jar delombok src -d src-delomboked

# 打印编译之后的Java文件
java -jar lombok.jar delombok -p MyJavaSourceFile.java
java -jar lombok.jar delombok -p E:\workspace\learning\src\main\java\org\curitis\lombok\User.java

文档资料

annotation-process
github
Lombok注解
Lombok下载
delombok
Lombok开始

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值