Java代碼冗餘?餓貨!來條 lombok吧!

引言

咱們在項目中常常遇到一些很冗餘的操做,致使一個小功能寫成大工程,那麼這時候咱們就要考慮是否該升級下咱們的技術了呢?擁抱 lombok,它會幫助咱們解決一些讓咱們很煩躁的問題。如下是應用結合網絡資料陸續整理而成的文檔。java

lombok解析流程

lombok解析流程.png

源碼由javac解析到AST後,交給lombok annotation模塊完成註解部分的解析工做,並輸出修改後的ASTspring

去掉 Setter 和 Getter

@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("不支持逆向轉化方法!");
            }
        }
    }

看到了吧,煩人的 GetterSetter 方法已經去掉了。網絡

bean 中的鏈式風格

改造前框架

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 命名是一種約定(俗話說:約定優於配置),它是指 ListsList 這個類的一個工具類,那麼使用 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

@Builder
public class Student {
    private String name;
    private int age;
}

調用方式:

Student student = Student.builder().name("zs").age(24).build();

代理模式

正如咱們所知的,在程序中調用 rest 接口是一個常見的行爲動做,若是你和我同樣使用過 springRestTemplate,我相信你會我和同樣,對他拋出的非 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。

其餘lombok註解

lambok還有不少註解,不一一解釋,你們能夠多嘗試:

@Data(包括@Getter、@Setter、@ToString、@EqualsAndHashCode)

@NoArgsConstructor

@AllArgsConstructor

@EqualsAndHashCode

@Slf4j          logback日誌框架時使用

@Log4j        Log4j日誌框架時使用

@ToString(exclude="")

@ToString(exclude={"",""})

@ToString(of="")

@ToString(of={"",""})

enjoy......

相關文章
相關標籤/搜索