---
# System prepended metadata

title: Lombok
tags: [Lombok]

---

---
title: 'Lombok'
disqus: hackmd
---
###### tags: `Lombok` 
不想再寫那麼多code啦 --- 學會Lombok用法
===

[TOC]

## Lombok是什麼

Lombok 是一個 Java library，可以透過簡單的注解省略 Java 的 code，像是 setter、getter、toString、logger…等，目的在消除冗長的 code 和提高開發效率
假設你在類上加上了一個 @Getter 和 @Setter 注解，那你就不用在寫煩人的 getter 和 setter，lombok 會自動幫你產生出來啦！

## 如何安裝

### Springboot專案導入
Pom 加入此Dependency
```pom
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    <scope>provided</scope>
</dependency>
```

### Eclipse IDE Install Lombok
[Eclipse install procedure](https://projectlombok.org/setup/eclipse)
After install successfully, then check
![About Eclipse IDE](https://i.imgur.com/u83i9ht.png)

## 有無Lombok比較

### 無Lombok
```java=
public class Customer_noLombok {
	

    private Long id;
	
    private String customerName;
    
    private String contectEmail;
    
    private Boolean isActive;
    
    private String customerStatus;
    
    

	public Customer_noLombok() {
		super();
	}



	public Customer_noLombok(Long id, String customerName, String contectEmail, Boolean isActive,
			String customerStatus) {
		super();
		this.id = id;
		this.customerName = customerName;
		this.contectEmail = contectEmail;
		this.isActive = isActive;
		this.customerStatus = customerStatus;
	}



	@Override
	public String toString() {
		return "Customer_noLombok [id=" + id + ", customerName=" + customerName + ", contectEmail=" + contectEmail
				+ ", isActive=" + isActive + ", customerStatus=" + customerStatus + "]";
	}



	public Long getId() {
		return id;
	}



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



	public String getCustomerName() {
		return customerName;
	}



	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}



	public String getContectEmail() {
		return contectEmail;
	}



	public void setContectEmail(String contectEmail) {
		this.contectEmail = contectEmail;
	}



	public Boolean getIsActive() {
		return isActive;
	}



	public void setIsActive(Boolean isActive) {
		this.isActive = isActive;
	}



	public String getCustomerStatus() {
		return customerStatus;
	}



	public void setCustomerStatus(String customerStatus) {
		this.customerStatus = customerStatus;
	}
}
```

### 有Lombok
```java=
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Customer {
	
    private Long id;
	
    private String customerName;
    
    private String contectEmail;
    
    private Boolean isActive;
    
    private String customerStatus;

}
```

## 如何使用

### @Getter/@Setter
> 省去寫getter/setter,每當新增parameter 可以不必再去 滑鼠右鍵->Source->Generate Getters and Setters

用法只需再類別上加上@Getter/@Setter 即可
```java=
@Getter
@Setter
public class Customer {
    ...
}
```

### @ToString
> 省去寫toString(),每當新增parameter 可以不必再去 滑鼠右鍵->Source->Generate toString(...)

用法只需再類別上加上@ToString 即可
```java=
@ToString
public class Customer {
    ...
}
```

### @NoArgsConstructor/@AllArgsConstructor
> 省去寫constructor,每當新增parameter 可以不必再去 滑鼠右鍵->Source->Generate constructor using fields...

> 但若是有多種組合的Constructor 還是得手動產生

用法只需再類別上加上@NoArgsConstructor/@AllArgsConstructor 即可
```java=
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
    ...
}
```
### @Builder
> 自動生成流式 set 值寫法，從此之後再也不用寫一堆 setter 了

用法只需再類別上加上@Builder 即可
```java=
@Builder
public class Customer {
    ...
}
```
無使用@Builder範例
```java=
Customer_noLombok newCustomer_noLombok = new Customer_noLombok();
newCustomer_noLombok.setContectEmail("hatethis@email.com");
newCustomer_noLombok.setCustomerName("hatehate");
newCustomer_noLombok.setCustomerStatus("died");
newCustomer_noLombok.setId(1L);
newCustomer_noLombok.setIsActive(false);
```
使用@Builder範例
```java=
Customer newCustomer_WithLombok = 
    Customer.builder()
    .contectEmail("feelgrate@email.com")
	.customerName("likelike")
	.customerStatus("alive")
	.id(100L)
	.isActive(true)
	.build();
```

### @Slf4j
> 不必手動在每個class都先宣告出logger,才能使用log物件啦
> Lombok 支援許多種不同log物件對應的Annotation也不同,但功能運作上是相同的概念,詳細查看專案所使用的log物件是哪一套查詢對應的@Annotation即可

用法只需再類別上加上@Slf4j 即可

使用@Slf4j範例
```java=
@Slf4j
public class LogExampleOther {
  
  public static void main(String... args) {
    log.error("Something else is wrong here");
  }
}
```

無使用@Slf4j範例
```java=
public class LogExample {
  private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
  
  public static void main(String... args) {
    log.severe("Something's wrong here");
  }
}
```

## Lombok的優缺點

### 優點：

* 能通過註解的形式自動生成構造器、getter/setter、equals、hashcode、toString等方法，提高了一定的開發效率
* 讓代碼變得簡潔，不用過多的去關注相應的方法
* 屬性做修改時，也簡化了維護為這些屬性所生成的getter/setter方法等

### 缺點：

* 不支持多種參數構造器的重載
* 因為Lombok的使用要求開發者一定要在IDE中安裝對應的插件。如果未安裝插件的話，使用IDE打開一個基於Lombok的項目的話會提示找不到方法等錯誤。導致項目編譯失敗。也就是說，如果項目組中有一個人使用了Lombok，那麼其他人就必須也要安裝IDE插件。否則就沒辦法協同開發。
* 如果我們定義的一個jar包中使用了Lombok，那麼就要求所有依賴這個jar包的所有應用都必須安裝插件，這種侵入性是很高的。
* 使用Lombok過程中，如果對於各種註解的底層原理不理解的話，很容易產生意想不到的結果
* 影響升級: JDK的升級頻率，每半年都會推出一個新的版本，但是Lombok作為一個第三方工具，並且是由開源團隊維護的，那麼他的迭代速度是無法保證的。所以，如果我們需要升級到某個新版本的JDK的時候，若其中的特性在Lombok中不支持的話就會受到影響。
* 還有一個可能帶來的問題，就是Lombok自身的升級也會受到限制。因為一個應用可能依賴了多個jar包，而每個jar包可能又要依賴不同版本的Lombok，這就導致在應用中需要做版本仲裁，而我們知道，jar包版本仲裁是沒那麼容易的，而且發生問題的概率也很高。

## 總結
> 雖然Lombok套件並非僅帶來好處,同樣的也伴隨著一些問題,但在有限度以及團隊定義好使用方式的情形下是可以導入此套件享受它帶來的便利性，因此為了避免我們團隊使用上可能遇到上述缺點,我們定義出底下規範來遵守並使用Lombok

* 建立團隊使用Lombok規範
    * Lombok版本一致性 <version>1.18.22</version>
    * JDK版本一致性 1.8
    * 清楚熟悉每個@Annotation的運作原理
    * 禁用@Data
    * 當有新的@Annotation需要支援團隊使用時,需先經過了解並測試,並分享於筆記上,開會與同仁分享使用方式並討論有無潛在風險,確認安全可控後,即可納入開放使用@Annotation
    * 確認可開放使用
        * @Getter
        * @Setter
        * @Builder
        * @NoArgsConstructor
        * @AllArgsConstructor
        * @ToString
        * @EqualsAndHashCode

## 參考來源

* [Project Lombok 官方](https://projectlombok.org/)
* [Lombok features](https://projectlombok.org/features/all)
* [Java - 五分鐘學會 Lombok 用法](https://kucw.github.io/blog/2020/3/java-lombok/)
* [Lombok 運作原理](https://codingnote.cc/zh-tw/p/83058/)
* [新來個技術總監，禁止我們使用Lombok！](https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/714065/)