lombok

Lombok,Lombok不是通过字节码改写来实现的。 http://jnb.ociweb.com/jnb/jnbJan2010.html
它主要是用编译器内支持的annotation processing,直接操纵抽象语法树(AST),根据需要添加新节点。

通过在编译阶段修改其结构来转换抽象语法树(AST)。AST 代表已解析源代码的树,它由编译器创建,与 XML 文件的 DOM 树模型类似。通过修改(或转换)AST,Lombok 可对源代码进行修剪,来避免膨胀,这与纯文本代码生成不同。Lombok 所生成的代码对于同一编译单元的类是可见的,这不同于带库的直接字符编码操作,比如 CGLib 或者 ASM。

不需要在运行时包含lombok.jar

什么是 AST 转换?

AST 转换 是在编译过程中用来修改抽象语法树结构的代码的名称。修改 AST,通过在将其转换为字节码之前增加附加节点,是更好的生成代码的方法。(这是相对于进行文本代码或直接生成字节码操作的常见技术而言。)直接采用 AST 还意味着开发人员需要访问编译器 API,这就引入了其他代码生成工具所不具备的,Lombok 的一个特性:自定义编译错误与警告功能。

 

 

 

Lombok的特色是根据annotation创建一些代码,以减少重复代码的数量,它提供了以下几个annotation:

@Getter和@Setter:为属性创建getter和setter

@EqualsAndHashCode:实现equals()方法和hashCode()方法

@ToString:实现toString()方法

@Data:上述3个annotation的和,会创建getter setter equals hashCode和toString,正如你上面看到的那样

@Cleanup:关闭流

@Synchronized:对象同步

@SneakyThrows:抛出异常,允许不在方法定义中声明所检查的异常,而将其扔掉,如同它们是未经检查的异常

@Data   :注解在类上;提供类所有属性的 getting 和 setting 方法,此外还提供了equals、canEqual、hashCode、toString 方法
        
@Setter:注解在属性上;为属性提供 setting 方法
        
@Getter:注解在属性上;为属性提供 getting 方法
        
@Log4j :注解在类上;为类提供一个 属性名为log 的 log4j 日志对象
        
@NoArgsConstructor:注解在类上;为类提供一个无参的构造方法
        
@AllArgsConstructor:注解在类上;为类提供一个全参的构造方法
@Tolerate

 @Log

val
Finally! Hassle-free final local variables.
@NonNull
or: How I learned to stop worrying and love the NullPointerException.
@Cleanup
Automatic resource management: Call your close() methods safely with no hassle.
@Getter / @Setter
Never write public int getFoo() {return foo;} again.
@ToString
No need to start a debugger to see your fields: Just let lombok generate a toString for you!
@EqualsAndHashCode
Equality made easy: Generates hashCode and equals implementations from the fields of your object.
@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor
Constructors made to order: Generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field.
@Data
All together now: A shortcut for @ToString, @EqualsAndHashCode, @Getter on all fields, and @Setter on all non-final fields, and @RequiredArgsConstructor!
@Value
Immutable classes made very easy.
@SneakyThrows
To boldly throw checked exceptions where no one has thrown them before!
@Synchronized
synchronized done right: Don't expose your locks.
@Getter(lazy=true)
Laziness is a virtue!
@Log
Captain's Log, stardate 24435.7: "What was that line again?"

一、注解

(1)

  • @Data:相当于同时使用了@ToString、@EqualsAndHashCode、@Getter、@Setter和@RequiredArgsConstructor这些注解,对于POJO类十分有用。
  • @NonNull:给方法参数增加这个注解会自动在方法内对该参数进行是否为空的校验,如果为空,则抛出NPE。
  • @Cleanup:自动生成try-finally这样的代码来关闭流(你一定写过使用-关闭流的样板代码)。不仅消除了 try/catch/finally 块,而且还关闭了开放流
  • @Getter(lazy=true):可以替代掉经典的Double Check Lock样板代码!
  • @Synchronized
  • 1,编程时需要写的源文件(Lure.java)。我们假设 数据对象不想去写getter/setter等方法;color 属性是不需要包含在toString()、equals()、hashCode()方法中;而且 size 属性是只有包可见访问限制;以及operate()方法要求同步,且内部逻辑需要简化 try/finally语句样式。 正如我们看到的,所需要写的代码如下所示,非常简洁。
    @ToString(exclude="color")
    @EqualsAndHashCode(exclude="color")
    public @Data class Lure {
        private String name;
        private @Getter(AccessLevel.PACKAGE) int size;
        private String color;
        private String style;
        private boolean active;
     
        @Synchronized
        public void operate(String[] args) throws IOException {
            @Cleanup InputStream in = new FileInputStream(args[0]);         
            @Cleanup OutputStream out = new FileOutputStream(args[1]);
            //write file code goes here
        }
    }
  • 然后,试试通过 Java Decompiler 获得反编译后的源文件(Lure.java)内部方法的实现情况会如何。正如我们看到的,Lombok 做得非常棒。它把我们编程时应该写的代码全部编织好了。仅仅是通过少量的特定的注释类。
    public class Lure {
     private String name;
     private int size;
     private String color;
     private String style;
     private boolean active;
     private final Object $lock; //因为@Synchronized注释
     public Lure() {
      this.$lock = new Object[0];//因为@Synchronized注释
     }
     public void operate(String[] args) throws IOException {
      synchronized (this.$lock) {//因为@Synchronized注释
       InputStream in = new FileInputStream(args[0]);
       try {//因为 @Cleanup注释
        OutputStream out = new FileOutputStream(args[1]);
        out.close();
       } finally {
        in.close();//因为 @Cleanup注释
       }
      }
     }
     int getSize() { return this.size; }//包可见访问限制, @Getter(AccessLevel.PACKAGE)注释
     public String toString() {//因为 @ToString(exclude="color")注释,见不到处理 color属性
      return "Lure(name=" + this.name + ", size=" + this.size + ", style="
        + this.style + ", active=" + this.active + ")";
     }
     /*
      * 因为@EqualsAndHashCode(exclude="color")注释,见不到处理 color属性
      * 此方法包含反编译生成代码时的错误,如break label64,与Lombok编织代码无关
      */
     public boolean equals(Object o) {
      if (o == this) return true;
      if (o == null) return false;
      if (o.getClass() != super.getClass()) return false;
      Lure other = (Lure) o;
      if (this.name == null)
       if (other.name == null) break label64;
       else if (this.name.equals(other.name)) break label64;
      return false;
      if (this.size != other.size) label64: return false;
      if (this.style == null)
       if (other.style == null) break label110;
       else if (this.style.equals(other.style)) break label110;
      return false;
      label110: return this.active == other.active;
     }
     /*
      * 因为@EqualsAndHashCode(exclude="color")注释,见不到处理 color属性
      * 存在反编译生成代码的情况,如 有 PRIME 的表达式,直接是 31, 与Lombok编织代码无关
      */
     public int hashCode() {
      int PRIME = 31;
      int result = 1;
      result = result * 31 + ((this.name == null) ? 0 : this.name.hashCode());
      result = result * 31 + this.size;
      result = result * 31 + ((this.style == null) ? 0 : this.style.hashCode());
      return result * 31 + ((this.active) ? 1231 : 1237);
     }
     /*
      * 因为 @Data注释,生成了随后的方法
      */
     public String getName() { return this.name; }
     public void setName(String name) { this.name = name; }
     public void setSize(int size) { this.size = size; }
     public String getColor() { return this.color; }
     public void setColor(String color) { this.color = color; }
     public String getStyle() { return this.style; }
     public void setStyle(String style) { this.style = style; }
     public boolean isActive() { return this.active; }
     public void setActive(boolean active) { this.active = active; }
    }

你可能感兴趣的:(lombok)