咱們在項目中常常遇到一些很冗餘的操做,致使一個小功能寫成大工程,那麼這時候咱們就要考慮是否該升級下咱們的技術了呢?擁抱 lombok
,它會幫助咱們解決一些讓咱們很煩躁的問題。如下是應用結合網絡資料陸續整理而成的文檔。java
源碼由javac
解析到AST
後,交給lombok annotation
模塊完成註解部分的解析工做,並輸出修改後的AST
。spring
@Setter @Getter public class UserDTO { @NotNull private String username; @NotNull private int age; public User convertToUser(){ UserDTOConvert userDTOConvert = new UserDTOConvert(); User convert = userDTOConvert.convert(this); return convert; } public UserDTO convertFor(User user){ UserDTOConvert userDTOConvert = new UserDTOConvert(); UserDTO convert = userDTOConvert.reverse().convert(user); return convert; } private static class UserDTOConvert extends Converter<UserDTO, User> { @Override protected User doForward(UserDTO userDTO) { User user = new User(); BeanUtils.copyProperties(userDTO,user); return user; } @Override protected UserDTO doBackward(User user) { throw new AssertionError("不支持逆向轉化方法!"); } } }
看到了吧,煩人的 Getter
和 Setter
方法已經去掉了。網絡
改造前框架
public class Student { private String name; private int age; public String getName() { return name; } public Student setName(String name) { this.name = name; return this; } public int getAge() { return age; } public Student setAge(int age) { return this; } }
相信合理使用這樣的鏈式代碼,會更多的程序帶來很好的可讀性,那看一下若是使用 lombok
進行改善呢,請使用 @Accessors(chain = true)
,看以下代碼:ide
@Accessors(chain = true) @Setter @Getter public class Student { private String name; private int age; }
這樣就完成了一個對於 bean
來說很友好的鏈式操做。工具
靜態構造方法的語義和簡化程度真的高於直接去 new
一個對象。好比 new
一個 List
對象,過去的使用是這樣的:post
List<String> list = new ArrayList<>();
看一下 guava
中的建立方式:測試
List<String> list = Lists.newArrayList();
Lists
命名是一種約定(俗話說:約定優於配置),它是指 Lists
是 List
這個類的一個工具類,那麼使用 List
的工具類去產生 List
,這樣的語義要比直接 new
一個子類來的更直接。再好比有一個工具類叫作 Maps
,那你是否想到了建立 Map
的方法呢:優化
HashMap<String, String> objectObjectHashMap = Maps.newHashMap();
接上上邊的靜態構造方法和必傳參數的構造方法,使用 lombok 將更改爲以下寫法(@RequiredArgsConstructor
和 @NonNull
):ui
@Accessors(chain = true) @Setter @Getter @RequiredArgsConstructor(staticName = "ofName") public class Student { @NonNull private String name; private int age; }
測試代碼:
Student student = Student.ofName("zs");
這樣構建出的 bean
語義是否要比直接 new
一個含參的構造方法(包含 name
的構造方法)要好不少。
固然,看過不少源碼之後,我相信將靜態構造方法 ofName
換成 of
會先的更加簡潔:
@Accessors(chain = true) @Setter @Getter @RequiredArgsConstructor(staticName = "of") public class Student { @NonNull private String name; private int age; }
測試代碼:
Student student = Student.of("zs");
固然他仍然是支持鏈式調用的:
Student student = Student.of("zs").setAge(24);
這樣來寫代碼,真的很簡潔,而且可讀性很強。
@Builder public class Student { private String name; private int age; }
調用方式:
Student student = Student.builder().name("zs").age(24).build();
正如咱們所知的,在程序中調用 rest 接口是一個常見的行爲動做,若是你和我同樣使用過 spring
的 RestTemplate
,我相信你會我和同樣,對他拋出的非 http
狀態碼異常深惡痛絕。
因此咱們考慮將 RestTemplate
最爲底層包裝器進行包裝器模式的設計:
public abstract class FilterRestTemplate implements RestOperations { protected volatile RestTemplate restTemplate; protected FilterRestTemplate(RestTemplate restTemplate){ this.restTemplate = restTemplate; } //實現RestOperations全部的接口 }
而後再由擴展類對 FilterRestTemplate
進行包裝擴展:
public class ExtractRestTemplate extends FilterRestTemplate { private RestTemplate restTemplate; public ExtractRestTemplate(RestTemplate restTemplate) { super(restTemplate); this.restTemplate = restTemplate; } public <T> RestResponseDTO<T> postForEntityWithNoException(String url, Object request, Class<T> responseType, Object... uriVariables) throws RestClientException { RestResponseDTO<T> restResponseDTO = new RestResponseDTO<T>(); ResponseEntity<T> tResponseEntity; try { tResponseEntity = restTemplate.postForEntity(url, request, responseType, uriVariables); restResponseDTO.setData(tResponseEntity.getBody()); restResponseDTO.setMessage(tResponseEntity.getStatusCode().name()); restResponseDTO.setStatusCode(tResponseEntity.getStatusCodeValue()); }catch (Exception e){ restResponseDTO.setStatusCode(RestResponseDTO.UNKNOWN_ERROR); restResponseDTO.setMessage(e.getMessage()); restResponseDTO.setData(null); } return restResponseDTO; } }
包裝器 ExtractRestTemplate
很完美的更改了異常拋出的行爲,讓程序更具備容錯性。在這裏咱們不考慮 ExtractRestTemplate
完成的功能,讓咱們把焦點放在 FilterRestTemplate
上,實現 RestOperations
全部的接口,這個操做絕對不是一時半會能夠寫完的:
public abstract class FilterRestTemplate implements RestOperations { protected volatile RestTemplate restTemplate; protected FilterRestTemplate(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @Override public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException { return restTemplate.getForObject(url,responseType,uriVariables); } @Override public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException { return restTemplate.getForObject(url,responseType,uriVariables); } @Override public <T> T getForObject(URI url, Class<T> responseType) throws RestClientException { return restTemplate.getForObject(url,responseType); } @Override public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables) throws RestClientException { return restTemplate.getForEntity(url,responseType,uriVariables); } //其餘實現代碼略。。。 }
我相信你看了以上代碼,你會和我同樣以爲噁心反胃,後來我用 lombok
提供的代理註解優化了個人代碼(@Delegate
):
@AllArgsConstructor public abstract class FilterRestTemplate implements RestOperations { @Delegate protected volatile RestTemplate restTemplate; }
這幾行代碼徹底替代上述那些冗長的代碼。@Delegate
解釋委託模式
,當時間E發生在類A身上時,A能夠經過@Delegate
將該事件委託給B處理,而且當B處理完成後,將結果返回給A。對於外部調用者C來講,他並不關心究竟是A仍是B完成了此次計算,他只關心最終的返回結果是否正確,這樣一來就大大解放了A。
lambok
還有不少註解,不一一解釋,你們能夠多嘗試:
@Data(包括@Getter、@Setter、@ToString、@EqualsAndHashCode)@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Slf4j logback日誌框架時使用
@Log4j Log4j日誌框架時使用
@ToString(exclude="")
@ToString(exclude={"",""})
@ToString(of="")
@ToString(of={"",""})
enjoy......