Здравствуйте, энтузиасты Java, давайте поговорим о Java и рефакторинге. Как мы все знаем, Java остается самым популярным языком программирования (ну, я так думаю) и заново изобретает себя, добавляя все больше и больше функций в каждый выпуск, превращаясь в идеальное сочетание объектно-ориентированного и функционального языков с введением Lambda expressions, Streams and CompletableFuture in Java_8.

Все мы знаем о Java-bean-компонентах, известных как POJO (обычные старые объекты Java), или DTO (объекты передачи данных). Несмотря на то, что соответствующие определения различаются в огромном сообществе Java, все они делают одно и то же. В основном разные имена, та же концепция.

Примечание. Я буду использовать термин DTO (объект передачи данных) для Java beans, также известного как POJO, в этой статье.

Общие черты DTO (объекты передачи данных):

  1. Все свойства должны быть частными.
  2. У него должен быть конструктор без аргументов.
  3. Он должен быть Serializable (в большинстве случаев, если он НЕ будет передаваться по сети).
  4. Он должен обеспечивать способы извлечения (получения) и изменения (установки) значения свойств с помощью методов получения и установки.

Подводя итог, DTO - это настраиваемые типы данных. И вышеупомянутый контракт - это просто соглашение. Это не стандарт Java и не шаблон проектирования, в конце концов, шаблон проектирования - это лучшая практика, доказавшая свою эффективность в решении реальных проблем.

Все идет нормально. Но вот в чем проблема. Что, если DTO содержит, скажем, 10 или более свойств. Вот как выглядит типичный DTO.

Давайте посмотрим на образец Employee_DTO, который содержит основную информацию о сотруднике.

import java.util.Date;

public class Employee_DTO {

    private int employeeId;
    private String name;
    private String email;
    private String department;
    private Employee_DTO manager;
    private Date joiningDate;
    private String designation;
    private String address;
    private int phoneNumber;
    private int emergencyContact;
    private int yearsAtCompany;
    private int totalExperienceInYears;

    public int getEmployeeId() {
        return employeeId;
    }

    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getDepartment() {
        return department;
    }

    public void setDepartment(String department) {
        this.department = department;
    }

    public Employee_DTO getManager() {
        return manager;
    }

    public void setManager(Employee_DTO manager) {
        this.manager = manager;
    }

    public Date getJoiningDate() {
        return joiningDate;
    }

    public void setJoiningDate(Date joiningDate) {
        this.joiningDate = joiningDate;
    }

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(int phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public int getEmergencyContact() {
        return emergencyContact;
    }

    public void setEmergencyContact(int emergencyContact) {
        this.emergencyContact = emergencyContact;
    }

    public int getYearsAtCompany() {
        return yearsAtCompany;
    }

    public void setYearsAtCompany(int yearsAtCompany) {
        this.yearsAtCompany = yearsAtCompany;
    }

    public int getTotalExperienceInYears() {
        return totalExperienceInYears;
    }

    public void setTotalExperienceInYears(int totalExperienceInYears) {
        this.totalExperienceInYears = totalExperienceInYears;
    }

}

Мы знаем, что это не очень хорошо с десятками геттеров и сеттеров. Конечно, это один из тех примеров для спагетти-кода, к тому же менее читаемый. Представьте себе, что у вас есть десятки или, может быть, сотни этих DTO, геттеров и сеттеров для всех этих DTO. Давайте не будем воображать (да, я имею в виду), поскольку у нас есть элегантный способ преодолеть это и, тем не менее, добиться того же с меньшим количеством шаблонного кода.

Именно здесь на сцену выходит Lombok. Он дает нам простые аннотации, которые легко понять, и помогает избежать всего шаблонного кода, который можно представить в DTO.

Как работает Ломбок за кадром:

Lombok сокращает шаблонный код с помощью аннотаций, выполняющих преобразования классов во время компиляции. Lombok поставляется с приличным набором преобразований, но вы также можете создать свои собственные Lombok преобразования.

Lombok работает как обработчик аннотаций. Обработчик аннотаций действует как диспетчер, который делегирует обработчики аннотаций Lombok (это то, что мы собираемся создать). Обработчики обнаруживаются через фреймворк под названием SPI. Обработчики аннотаций Lombok объявляют конкретную аннотацию, которую они обрабатывают. При делегировании обработчику обработчик аннотаций Lombok предоставляет объект, представляющий абстрактное синтаксическое дерево (AST) аннотированного узла (например, класс, метод, поле и т. Д.). Обработчик аннотаций Lombok может изменять AST, добавляя новые узлы, такие как методы, поля и выражения. После этапа обработки аннотации компилятор сгенерирует байтовый код из измененного AST.

Короче говоря, Lombok вообще не генерирует код. Вместо этого он использует неуказанные и недокументированные вызовы API внутренней реализации компилятора для непосредственного изменения абстрактного синтаксического дерева программы между чтением исходного кода и выводом скомпилированного байтового кода.

Ладно, теория отдельно. Посмотрим, как быстро мы сможем ввести Lombok в наш Java-проект: зависимость maven наверняка выглядит так:

И Employee_DTO, проиллюстрированный выше, выглядит намного элегантнее и удобочитаемее с Lombok. Давайте рассмотрим несколько примеров, которые показывают, как Lombok аннотации могут использоваться и что они значат для нас.

  1. Геттеры и сеттеры Lombok, применяемые ко всему DTO:

@Getter и @Setterаннотации применяются ко всему классу, как показано ниже.

import lombok.Getter;
import lombok.Setter;

import java.util.Date;

@Getter
@Setter
public class Employee_DTO_Lombok {

    private int employeeId;
    private String name;
    private String email;
    private String department;
    private Employee_DTO manager;
    private Date joiningDate;
    private String designation;
    private String address;
    private int phoneNumber;
    private int emergencyContact;
    private int yearsAtCompany;
    private int totalExperienceInYears;

}

2. Геттеры и сеттеры Lombok, применяемые выборочно в данном DTO:

И если нам нужны только методы получения и установки для выбранных переменных / свойств, мы также можем это сделать.

3. Ломбок на замену конструкторам:

а) Замена конструктора All-Args:

Иногда вы не хотите предоставлять методы установки и требовать, чтобы клиент устанавливал значения только путем вызова конструктора.

Пример Java DTO с конструктором All-args.

После замены конструктора All-args в приведенном выше фрагменте кода аннотацией @ AllArgsConstructor все сводится к примерно следующему.

б) Замена конструктора без аргументов:

И замена конструктора No-Args ничем не отличается.

c) Определение спецификаторов доступа для конструкторов:

При работе с Kryo сериализацией и десериализацией необходимо иметь конструктор без аргументов с частным доступом и, к счастью, Lombok также обращается к таким сценариям, поэтому вот пример, в котором мы можем определить спецификаторы доступа для конструкторов:

4. Ломбок для создания метода toString ():

Он также генерирует метод toString() по умолчанию с учетом всех свойств в DTO с сохранением их порядка.

при печати это выглядит так

Person_DTO(personName=John Smith, personAddress=4th Avenue-LA, phoneNum=1234567890, [email protected])

5. Lombok для создания методов equals () и hashCode ():

@EqualsAndHashCode генерирует реализации методов equals(Object other) и hashCode(). По умолчанию он будет использовать все нестатические, непереходные поля, но вы можете изменить используемые поля (и даже указать, что должен использоваться вывод различных методов), пометив элементы типа @EqualsAndHashCode.Include или @EqualsAndHashCode.Exclude. Кроме того, вы можете точно указать, какие поля или методы вы хотите использовать, пометив их знаком @EqualsAndHashCode.Include и используя @EqualsAndHashCode(onlyExplicitlyIncluded = true).

6. @Data: ярлык для @ToString, @EqualsAndHashCode, @Getter во всех полях, @Setter во всех незавершенных полях и @RequiredArgsConstructor

@RequiredArgsConstructor создает конструктор с 1 параметром для каждого поля, требующего специальной обработки. Все неинициализированные final поля получают параметр, а также любые поля, помеченные как @NonNull, которые не инициализированы там, где они объявлены.

что равносильно упоминанию всех аннотаций, перечисленных в приведенном ниже фрагменте кода.

В проекте Lombok доступны и другие аннотации / утилиты, которые очень полезны и пригодятся.

Назову несколько, @var, @val, @NonNull, @Cleanup, @Value, @Builder.

Очень легко реорганизовать существующий код / ​​проект и ввести Lombok с гораздо меньшими усилиями, ничего не сломав. Как упоминалось ранее, это делает код намного чище и делает элегантным и простым существующим кодом.

Добавление плагина Lombok в IDE:

Примечание. Если вы используете Eclipse или IntelliJ, простое добавление Lombok зависимости в pom.xml не всегда работает, и Lombok подключаемый модуль необходимо добавить вручную в соответствующую среду IDE.

1. Добавление плагина Lombok в IntelliJ:

  1. Нажмите Command + запятая («⌘» + «,»)
  2. Найдите «плагин» в верхнем левом углу окна.
  3. Переключите вкладку, т. Е. Перейдите на «торговая площадка»
  4. Найдите «lombok» и нажмите «установить».
  5. Перезапустите IntelliJ

2. Добавление плагина Lombok в Eclipse:

  1. Сначала возьмите банку Ломбока. Последняя версия находится на Maven Central.
  2. Запустите jar с помощью команды java -jar, и откроется пользовательский интерфейс установщика.
  3. Выбрав установки, мы нажимаем кнопку Установить / Обновить и выходим из установщика.
  4. После установки плагина перезапустите Eclipse и убедитесь, что Lombok правильно настроен.

Болевые точки:

  1. Возможно, вам придется переключиться на «общедоступное соединение Wi-Fi вашей организации», чтобы иногда иметь возможность искать и устанавливать плагины.
  2. Если вы подключены к VPN, попробуйте отключиться от него и добавить плагин.
  3. Измените настройки прокси-сервера в IDE , если описанные выше уловки не работают, и попробуйте добавить плагин еще раз.
Interesting reads:
1. Load Balancers: A deep dive
2. Futures in Java: CompletableFuture

Удачного рефакторинга!

Следуй за мной Twitter, LinkedIn: Twitter, LinkedIn

Ресурсы:

  1. Https://projectlombok.org
  2. Https://stackoverflow.com/questions/6107197/how-does-lombok-work
  3. Http://notatube.blogspot.com/2010/12/project-lombok-creating-custom.html
  4. Https://stackoverflow.com/questions/3295496/what-is-a-javabean-exactly
  5. Https://www.baeldung.com/lombok-ide