深入Lombok

Lombok注解详解

本博客转载于此

概述

Lambok能以简单的注解形式来简化java代码。例如实际开发中经常需要需要写的javabean,需要花时间去写getter/setter方法,也许还要写构造器,equals等方法,显得代码冗余。

Lambok能通过注解的方式,在编译时自动为属性生成构造器,getter/setter,equals,hashcode等方法…

添加依赖

在pom.xml文件中添加相关依赖:

<lombok.version>1.16.20</lombok.version>

<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>${lombok.version}</version>
     <scope>provided</scope>
</dependency>
安装插件

以 idea 为例:查找插件 lombok plugin 安装即可

常用注解
@Data

@Data注解在类上,会为类的所有属性自动生成setter/getter,equals,canEqual,hashCode,toString方法,如为final属性,则不会为该属性生成setter方法

@Getter/@Setter

如果觉得@Data太过残暴(因为@Data集合了@ToString、@EqualsAndHashCode、@Getter/@Setter、@RequiredArgsConstructor的所有特性)不够精细,可以使用@Getter/@Setter注解,此注解在属性上,可以为相应的属性自动生成Getter/Setter方法

@NonNull

该注解用在属性或构造器上,Lombok会生成一个非空的声明,可用于校验参数,能帮助避免空指针,相当于数据校验

public class NonNullExample extends Something {
  private String name;
  
  public NonNullExample(@NonNull Person person) {
    super("Hello");
    this.name = person.getName();
  }
}
@Cleanup

该注解能帮助我们自动调用close()方法,很大的简化了代码

public class CleanupExample {
  public static void main(String[] args) throws IOException {
    @Cleanup InputStream in = new FileInputStream(args[0]);
    @Cleanup OutputStream out = new FileOutputStream(args[1]);
    byte[] b = new byte[10000];
    while (true) {
      int r = in.read(b);
      if (r == -1) break;
      out.write(b, 0, r);
    }
  }
}
@EqualsAndHashCode

默认情况下,会使用所有非静态(non-static)和非瞬态(non-transient)属性来生成equals和hasCode,也能通过exclude注解来排除一些属性

@EqualsAndHashCode(exclude={"id", "shape"})
public class EqualsAndHashCodeExample {
  private transient int transientVar = 10;
  private String name;
  private double score;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;
  
  public String getName() {
    return this.name;
  }
@ToString

类使用@ToString注解,Lombok会生成一个toString()方法,默认情况下,会输出类名、所有属性(会按照属性定义顺序),用逗号来分割。通过将includeFieldNames参数设为true,就能明确的输出toString()属性

//排除id
@ToString(exclude="id")
public class ToStringExample {
  private static final int STATIC_VAR = 10;
  private String name;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  private int id;
  
  public String getName() {
    return this.getName();
  }
  
  @ToString(callSuper=true, includeFieldNames=true)
  public static class Square extends Shape {
    private final int width, height;
    
    public Square(int width, int height) {
      this.width = width;
      this.height = height;
    }
  }
}
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor

无参构造器、部分参数构造器、全参构造器。Lombok没法实现多种参数构造器的重载

@RequiredArgsConstructor(staticName = "of")
//类权限
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ConstructorExample<T> {
  private int x, y;
  @NonNull private T description;
  
  @NoArgsConstructor
  public static class NoArgsExample {
    @NonNull private String field;
  }
}
Lombok工作原理

Lombok使用的过程中,只需要添加相应的注解,无需再为此写相应的代码。那么代码是如何自动生成的呢?
核心之处就是对于注解的解析上,JDK5引入注解的同时,也提供了两种解析方式

  1. 运行时解析:运行时能够解析的注解,必须将@Retention设置为RUNTIME,这样就可以通过反射拿到该注解。java.lang,reflect反射包中提供了一个接口AnnotatedElement,该接口定义了获取注解信息的几个方法,Class、Constructor、Field、Method、Package等都实现了该接口

  2. 编译时解析: 编译时解析有两种机制:

    1. Annotation Processing Tool:已经淘汰
    2. luggable Annotation Processing API:JSR 269自JDK6加入,作为apt的替代方案,它解决了apt两个问题,javac在执行的时候会调用实现了该API的程序,这样我们就可以对编译器进行增强

在这里插入图片描述
Lombok本质上就是一个实现了“JSR 269 API”的程序。在使用javac的过程中,它产生作用的具体流程如下:

  1. javac对源代码进行分析,生成了一棵抽象语法树(AST)
  2. 运行过程中调用实现了“JSR 269 API”的Lombok程序
  3. 此时Lombok就对第一步骤得到的AST进行处理,找到@Data注解所在类对应的语法树(AST),然后修改该语法树(AST),增加getter和setter方法定义的相应树节点
  4. javac使用修改后的抽象语法树(AST)生成字节码文件,即给class增加新的节点(代码块)
小结

Lombok就相当于拦截器,在编译源代码时,对标注了相应了注解的AST进行相应的操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值