1. 簡介
??Project Lombok makes java a spicier language by adding ‘handlers’ that know how to build and compile simple, boilerplate-free, not-quite-java code.
即Lombok通過增加一些“處理程序”,可以讓java變得簡潔、快速。
??Lombok能通過注解的方式,在編譯時自動為屬性生成構(gòu)造器、getter/setter、equals、hashcode、toString方法。同時可以自動化日志變量。
2. 引入Lombok
??使用Lombok需要的開發(fā)環(huán)境Java+Maven+IntelliJ IDEA或者Eclipse(安裝Lombok Plugin)。
2.1 添加maven依賴
<!-- 引入lombok依賴 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
2.2 idea安裝插件
??打開idea的設置,點擊Plugins,點擊Browse repositories,在彈出的窗口中搜索lombok,然后安裝即可。
2.3 編譯時出錯問題
編譯時出錯,可能是沒有enable注解處理器。在設置中找到Annotation Processors > Enable annotation processing。設置完成之后程序正常運行。
2.4 常用注解
@Setter :注解在類或字段,注解在類時為所有字段生成setter方法,注解在字段上時只為該字段生成setter方法。
@Getter :使用方法同上,區(qū)別在于生成的是getter方法。
@ToString :注解在類,生成toStirng方法。
@EqualsAndHashCode :注解在類,生成hashCode和equals方法。
@Data :注解在類,生成setter/getter、equals、canEqual、hashCode、toString方法,如為final屬性,則不會為該屬性生成setter方法。
@NoArgsConstructor :注解在類,生成無參的構(gòu)造方法。
@AllArgsConstructor :注解在類,生成包含類中所有字段的全參的構(gòu)造方法。
@RequiredArgsConstructor :注解在類,為類中需要特殊處理的字段生成構(gòu)造方法,比如final和被@NonNull注解的字段。
@Log4j :注解在類上;為類提供一個 屬性名為log 的 log4j 日志對象
@Slf4j :注解在類,生成log變量,嚴格意義來說是常量。private static final Logger log = LoggerFactory.getLogger(UserController.class);
==注意:== 在使用以上注解需要處理參數(shù)時,處理方法如下(以@ToString注解為例,其他注解同@ToString注解):
@ToString(exclude="column")
意義:排除column列所對應的元素,即在生成toString方法時不包含column參數(shù);@ToString(exclude={"column1","column2"})
意義:排除多個column列所對應的元素,其中間用英文狀態(tài)下的逗號進行分割,即在生成toString方法時不包含多個column參數(shù);@ToString(of="column")
意義:只生成包含column列所對應的元素的參數(shù)的toString方法,即在生成toString方法時只包含column參數(shù);;@ToString(of={"column1","column2"})
意義:只生成包含多個column列所對應的元素的參數(shù)的toString方法,其中間用英文狀態(tài)下的逗號進行分割,即在生成toString方法時只包含多個column參數(shù);
==----------------------------------------------------------------------------------------------------==
- @Cleanup : 可以關(guān)閉流
- @Builder : 被注解的類加個構(gòu)造者模式
- @Synchronized : 加個同步鎖
- @SneakyThrows : 等同于try/catch 捕獲異常
- @NonNull : 如果給參數(shù)加個這個注解,參數(shù)為null會拋出空指針異常
- @Value : 注解和@Data類似,區(qū)別在于它會把所有成員變量默認定義為private final修飾,并且不會生成set方法。
- @Accessors:注解在類或者屬性上;主要用于控制生成的getter和setter。
??fluent: boolean值,默認為false。此字段主要為控制生成的getter和setter方法前面是否帶get/set
??chain :boolean值,默認false。如果設置為true,setter返回的是此對象,方便鏈式調(diào)用方法
??prefix: 設置前綴 例如:@Accessors(prefix = “abc”) private String abcAge; 當生成get/set方法時,會把此前綴去掉。
3. 工作原理
lombok的核心之處就是對于注解的解析上。
JDK5引入了注解的同時,也提供了兩種解析方式:
- 運行時解析:
?運行時能夠解析的注解,必須將@Retention設置為RUNTIME,這樣就可以通過反射拿到該注解。java.lang.reflect反射包中提供了一個接口AnnotatedElement,該接口定義了獲取注解信息的幾個方法,Class、Constructor、Field、Method、Package等都實現(xiàn)了該接口。 - 編譯時解析:
?編譯時解析有兩種機制,分別簡單描述下:- Annotation Processing Tool
apt自JDK5產(chǎn)生,JDK7已標記為過期,不推薦使用,JDK8中已徹底刪除,自JDK6開始,可以使用Pluggable Annotation Processing API來替換它,apt被替換主要有2點原因:
api都在com.sun.mirror非標準包下;沒有集成到javac中,需要額外運行。 -
Pluggable Annotation Processing API
JSR 269自JDK6加入,作為apt的替代方案,它解決了apt的兩個問題,javac在執(zhí)行的時候會調(diào)用實現(xiàn)了該API的程序,這樣我們就可以對編譯器做一些增強,javac執(zhí)行的過程如下:
在這里插入圖片描述
Lombok本質(zhì)上就是一個實現(xiàn)了“JSR 269 API”的程序。在使用javac的過程中,它產(chǎn)生作用的具體流程如下:
- javac對源代碼進行分析,生成了一棵抽象語法樹(AST);
- 運行過程中調(diào)用實現(xiàn)了“JSR 269 API”的Lombok程序;
- 此時Lombok就對第一步驟得到的AST進行處理,找到@Data注解所在類對應的語法樹(AST),然后修改該語法樹(AST),增加getter和setter方法定義的相應樹節(jié)點;
- javac使用修改后的抽象語法樹(AST)生成字節(jié)碼文件,即給class增加新的節(jié)點(代碼塊)。通過讀Lombok源碼,發(fā)現(xiàn)對應注解的實現(xiàn)都在HandleXXX中,比如@Getter注解的實現(xiàn)在HandleGetter.handle()。還有一些其它類庫使用這種方式實現(xiàn),比如Google Auto、Dagger等等。
- Annotation Processing Tool
4. Lombok的優(yōu)缺點
優(yōu)點:
- 能通過注解的形式自動生成構(gòu)造器、getter/setter、equals、hashcode、toString等方法,提高了一定的開發(fā)效率;
- 讓代碼變得簡潔,不用過多的去關(guān)注相應的方法;
- 屬性做修改時,也簡化了維護為這些屬性所生成的getter/setter方法等;
缺點:
- 不支持多種參數(shù)構(gòu)造器的重載;;
- 雖然省去了手動創(chuàng)建getter/setter方法的麻煩,但大大降低了源代碼的可讀性和完整性,降低了閱讀源代碼的舒適度;
