Java效率工具Lombok使用及原理
一、前言 效率的提升
java效率的提升,一種方式就是去除模板程式碼。
1.1 去除pojo中的模板程式碼
pojo 的 getter/setter/tostring,異常處理,io流的關閉操作。等重複程式碼的出現。
解決方案:Lombok的使用。
二、lombok的使用
2.1 maven包
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> <scope>provided</scope> </dependency>
Lombok的scope=provided,說明它只在編譯階段生效,不需要打入包中。事實正是如此,Lombok在編譯期將帶Lombok註解的Java檔案正確編譯為完整的Class檔案。
2.2 ide 工具對lombok的支援
idea 對 lombok的支援
點選File-- Settings設定介面,開啟Annocation Processors:
三、Lombok實現原理
自從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)生成位元組碼檔案
四、Lombok的使用
POJO類常用註解:
@Getter/@Setter: 作用類上,生成所有成員變數的getter/setter方法;作用於成員變數上,生成該成員變數的getter/setter方法。可以設定訪問許可權及是否懶載入等。
package com.trace;
import lombok.AccessLevel;import lombok.Getter;import lombok.Setter;
/** * Created by Trace on 2018/5/19.<br/> * DESC: 測試類 */@SuppressWarnings("unused")public class TestClass {
public static void main(String[] args) {
}
@Getter(value = AccessLevel.PUBLIC)
@Setter(value = AccessLevel.PUBLIC)
public static class Person {
private String name;
private int age;
private boolean friendly;
}
public static class Animal {
private String name;
private int age;
@Getter @Setter private boolean funny;
}
}
在Structure檢視中,可以看到已經生成了getter/setter等方法:
編譯後的程式碼如下:[這也是傳統Java程式設計需要編寫的樣板程式碼]
//// Source code recreated from a .class file by IntelliJ IDEA// (powered by Fernflower decompiler)//
package com.trace;
public class TestClass { public TestClass() { }
public static void main(String[] args) { }
public static class Animal { private String name; private int age; private boolean funny;
public Animal() { }
public boolean isFunny() { return this.funny; }
public void setFunny(boolean funny) { this.funny = funny; } }
public static class Person { private String name; private int age; private boolean friendly;
public Person() { }
public String getName() { return this.name; }
public int getAge() { return this.age; }
public boolean isFriendly() { return this.friendly; }
public void setName(String name) { this.name = name; }
public void setAge(int age) { this.age = age; }
public void setFriendly(boolean friendly) { this.friendly = friendly; } }}
@ToString:作用於類,覆蓋預設的toString()方法,可以通過of屬性限定顯示某些欄位,通過exclude屬性排除某些欄位。
@EqualsAndHashCode:作用於類,覆蓋預設的equals和hashCode
@NonNull:主要作用於成員變數和引數中,標識不能為空,否則丟擲空指標異常。
@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor:作用於類上,用於生成建構函式。有staticName、access等屬性。
staticName屬性一旦設定,將採用靜態方法的方式生成例項,access屬性可以限定訪問許可權。
@NoArgsConstructor:生成無參構造器;
@RequiredArgsConstructor:生成包含final和@NonNull註解的成員變數的構造器;
@AllArgsConstructor:生成全參構造器。
編譯後結果:
public static class Person { @NonNull private String name; private int age; private boolean friendly;
public String toString() { return "TestClass.Person(name=" + this.getName() + ", age=" + this.getAge() + ")"; }
@NonNull public String getName() { return this.name; }
public int getAge() { return this.age; }
public boolean isFriendly() { return this.friendly; }
public void setName(@NonNull String name) { if(name == null) { throw new NullPointerException("name"); } else { this.name = name; } }
public void setAge(int age) { this.age = age; }
public void setFriendly(boolean friendly) { this.friendly = friendly; }
private Person() { }
private static TestClass.Person of() { return new TestClass.Person(); }
@ConstructorProperties({"name"}) Person(@NonNull String name) { if(name == null) { throw new NullPointerException("name"); } else { this.name = name; } }
@ConstructorProperties({"name", "age", "friendly"}) public Person(@NonNull String name, int age, boolean friendly) { if(name == null) { throw new NullPointerException("name"); } else { this.name = name; this.age = age; this.friendly = friendly; } }}
@Data:作用於類上,是以下註解的集合:@ToString @EqualsAndHashCode @Getter @Setter @RequiredArgsConstructor
@Builder:作用於類上,將類轉變為建造者模式
@Log:作用於類上,生成日誌變數。針對不同的日誌實現產品,有不同的註解:
其他重要註解:
@Cleanup:自動關閉資源,針對實現了java.io.Closeable介面的物件有效,如:典型的IO流物件
編譯後結果如下:
是不是簡潔了太多。
@SneakyThrows:可以對受檢異常進行捕捉並丟擲,可以改寫上述的main方法如下: https://mmbiz.qpic.cn/mmbiz_png/8yRv8Dibia2spfAUHyKgfqaAyP6mQxsicn1j3a5Ydyw36QYbcub1RQibIwW0yQ7IVWdOrbve7gSfXMdVFOLY2ysScw/640?wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1
@Synchronized:作用於方法級別,可以替換synchronize關鍵字或lock鎖,用處不大。