lombok简介

Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注解,用来消除Java类中的大量样板代码。仅五个字符(@Data)就可以替换数百行代码从而产生干净,简洁且易于维护的Java类。

 lombok官网地址:Project Lombok

 lombok maven坐标

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

lombok 注解

@Data 注解

定义一个Person 类,使用@Data注解

@Data
public class Person {
    private Integer id;

    private String name;

    private Date birthday;
}

编译后,生成的Person.class 文件

import java.util.Date;

public class Person {
    private Integer id;
    private String name;
    private Date birthday;

    public Person() {
    }

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

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

    public Date getBirthday() {
        return this.birthday;
    }

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

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

    public void setBirthday(final Date birthday) {
        this.birthday = birthday;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Person)) {
            return false;
        } else {
            Person other = (Person)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$id = this.getId();
                    Object other$id = other.getId();
                    if (this$id == null) {
                        if (other$id == null) {
                            break label47;
                        }
                    } else if (this$id.equals(other$id)) {
                        break label47;
                    }

                    return false;
                }

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

                Object this$birthday = this.getBirthday();
                Object other$birthday = other.getBirthday();
                if (this$birthday == null) {
                    if (other$birthday != null) {
                        return false;
                    }
                } else if (!this$birthday.equals(other$birthday)) {
                    return false;
                }

                return true;
            }
        }
    }

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

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.getId();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $name = this.getName();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        Object $birthday = this.getBirthday();
        result = result * 59 + ($birthday == null ? 43 : $birthday.hashCode());
        return result;
    }

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

可以看出@Data注解,可以生产get  set   equals  hashCode   toString等方法。

@Getter 和 @Setter注解

@Getter
@Setter
public class Person {
    private Integer id;

    private String name;

    private Date birthday;
}

编译后生成的.class文件

import java.util.Date;

public class Person {
    private Integer id;
    private String name;
    private Date birthday;

    public Person() {
    }

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

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

    public Date getBirthday() {
        return this.birthday;
    }

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

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

    public void setBirthday(final Date birthday) {
        this.birthday = birthday;
    }
}

@ToString注解

@Getter
@ToString
public class Person {
    private Integer id;

    private String name;

    private Date birthday;
}

编译后,生成的.class文件

import java.util.Date;

public class Person {
    private Integer id;
    private String name;
    private Date birthday;

    public Person() {
    }

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

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

    public Date getBirthday() {
        return this.birthday;
    }

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

@NoArgsConstructor 和 @AllArgsConstructor 注解

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private Integer id;

    private String name;

    private Date birthday;
}

 编译后,生成的.class文件

import java.util.Date;

public class Person {
    private Integer id;
    private String name;
    private Date birthday;

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

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

    public Date getBirthday() {
        return this.birthday;
    }

    public Person() {
    }

    public Person(final Integer id, final String name, final Date birthday) {
        this.id = id;
        this.name = name;
        this.birthday = birthday;
    }
}

@Accessors 注解

@Data
@Accessors(chain = true, fluent = true)
public class Person {
    private Integer id;

    private String name;

    private Date birthday;
}

 编译后,生成的.class文件

import java.util.Date;

public class Person {
    private Integer id;
    private String name;
    private Date birthday;

    public Person() {
    }

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

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

    public Date birthday() {
        return this.birthday;
    }

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

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

    public Person birthday(final Date birthday) {
        this.birthday = birthday;
        return this;
    }

    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof Person)) {
            return false;
        } else {
            Person other = (Person)o;
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47: {
                    Object this$id = this.id();
                    Object other$id = other.id();
                    if (this$id == null) {
                        if (other$id == null) {
                            break label47;
                        }
                    } else if (this$id.equals(other$id)) {
                        break label47;
                    }

                    return false;
                }

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

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

                return true;
            }
        }
    }

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

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $id = this.id();
        int result = result * 59 + ($id == null ? 43 : $id.hashCode());
        Object $name = this.name();
        result = result * 59 + ($name == null ? 43 : $name.hashCode());
        Object $birthday = this.birthday();
        result = result * 59 + ($birthday == null ? 43 : $birthday.hashCode());
        return result;
    }

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

lombok原理

我们先看下lombok的maven 坐标导入

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

maven 的 scope 范围

  • compile 的范围:当我们在pom.xml文件中的<scope></scope>标签中依赖为compile的时候,会在编译的时候将这个依赖加入进来,并且在打包(mvn package)的时候也会将这个依赖加入进去。简单来说就是编译和打包的时候直接加入,其他时候不会加入。
  • provided的范围  :在编译和测试的时候有效,在执行(mvn package)进行打包jar或者war包的时候不会加入,如果加入会出现包的冲突。
  • test的范围:意思是在测试的时候才会真正生效,但是其他的时候就不会,比如单元测试的时候你加入@Test注解时候会自己生效的,不用管它。
  • runtime的范围:同理在运行的时候才会依赖,在编译的时候不会依赖啦。

lombok的scope 范围是provided,那么在mvn package时不会加入。

@Retention 详解

@Data注解代码

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Data {
	/**
	 * If you specify a static constructor name, then the generated constructor will be private, and
	 * instead a static factory method is created that other classes can use to create instances.
	 * We suggest the name: "of", like so:
	 * 
	 * <pre>
	 *     public @Data(staticConstructor = "of") class Point { final int x, y; }
	 * </pre>
	 * 
	 * Default: No static constructor, instead the normal constructor is public.
	 * 
	 * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
	 */
	String staticConstructor() default "";
}

@Retention作用是定义被它所注解的注解保留多久,一共有三种策略,定义在RetentionPolicy枚举中 

  • source:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;被编译器忽略。
  • class:注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期。
  • runtime:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

这3个生命周期分别对应于:Java源文件(.java文件) ---> .class文件 ---> 内存中的字节码。

lombok 编译流程

java lombok 属性默认值 java lombok原理_spring

自从Java 6起,javac就支持“JSR 269 Pluggable Annotation Processing API”规范,只要程序实现了该API,就能在javac运行的时候得到调用。Lombok就是一个实现了"JSR 269 API"的程序。在使用javac的过程中,它产生作用的具体流程如下:

  1. javac对源代码进行分析,生成一棵抽象语法树(AST)。
  2. javac编译过程中调用实现了JSR 269的Lombok程序
  3. 此时Lombok就对第一步骤得到的AST进行处理,找到Lombok注解所在类对应的语法树       (AST),然后修改该语法树(AST),增加Lombok注解定义的相应树节点。
  4. javac使用修改后的抽象语法树(AST)生成字节码文件。

参考:

https://www.jianshu.com/p/29a08cb44b16

Lombok的基本使用 - 简书