«1. Обзор

В этом кратком руководстве мы рассмотрим определение «Обычный старый объект Java» или сокращенно POJO.

Мы рассмотрим, как POJO сравнивается с JavaBean, и как может быть полезно преобразование наших POJO в JavaBeans.

2. Обычные старые объекты Java

2.1. Что такое ПОЖО?

Когда мы говорим о POJO, мы описываем простой тип без ссылок на какие-либо конкретные фреймворки. POJO не имеет соглашения об именах для наших свойств и методов.

Давайте создадим базовый POJO сотрудника. У него будет три свойства; имя, фамилия и дата начала:

public class EmployeePojo {

    public String firstName;
    public String lastName;
    private LocalDate startDate;

    public EmployeePojo(String firstName, String lastName, LocalDate startDate) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.startDate = startDate;
    }

    public String name() {
        return this.firstName + " " + this.lastName;
    }

    public LocalDate getStart() {
        return this.startDate;
    }
}

Этот класс может использоваться любой программой Java, поскольку он не привязан ни к какой структуре.

Но мы не следуем никакому реальному соглашению по конструированию, доступу или изменению состояния класса.

Это отсутствие соглашения вызывает две проблемы:

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

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

Чтобы изучить этот второй момент, давайте поработаем с EmployeePojo, используя отражение. Таким образом, мы начнем находить некоторые из его ограничений.

2.2. Отражение с POJO

Давайте добавим в наш проект зависимость commons-beanutils:

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.4</version>
</dependency>

А теперь давайте проверим свойства нашего POJO:

List<String> propertyNames =
  PropertyUtils.getPropertyDescriptors(EmployeePojo.class).stream()
    .map(PropertyDescriptor::getDisplayName)
    .collect(Collectors.toList());

Если бы мы распечатали имена свойств в console, мы бы увидели только:

[start]

Здесь мы видим, что мы получаем start только как свойство класса. PropertyUtils не удалось найти два других.

Мы бы увидели тот же результат, если бы использовали другие библиотеки, такие как Jackson, для обработки EmployeePojo.

В идеале мы должны увидеть все наши свойства: firstName, lastName и startDate. И хорошая новость заключается в том, что многие библиотеки Java по умолчанию поддерживают то, что называется соглашением об именах JavaBean.

3. JavaBeans

3.1. Что такое JavaBean?

JavaBean по-прежнему является POJO, но вводит строгий набор правил его реализации:

    Уровни доступа — наши свойства являются закрытыми, и мы открываем геттеры и сеттеры Имена методов — наши геттеры и сеттеры следуют соглашение getX и setX (в случае логического значения isX может использоваться для получения) Конструктор по умолчанию — должен присутствовать конструктор без аргументов, чтобы экземпляр мог быть создан без предоставления аргументов, например, во время десериализации Сериализуемый — – реализация интерфейса Serializable позволяет нам хранить состояние

3.2. EmployeePojo как JavaBean

Итак, давайте попробуем преобразовать EmployeePojo в JavaBean:

public class EmployeeBean implements Serializable {

    private static final long serialVersionUID = -3760445487636086034L;
    private String firstName;
    private String lastName;
    private LocalDate startDate;

    public EmployeeBean() {
    }

    public EmployeeBean(String firstName, String lastName, LocalDate startDate) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.startDate = startDate;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    //  additional getters/setters

}

3.3. Отражение с помощью JavaBean

Когда мы проверяем наш bean-компонент с помощью отражения, мы получаем полный список свойств:

[firstName, lastName, startDate]

4. Компромиссы при использовании JavaBean

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

Когда мы используем JavaBeans, мы также должны помнить о некоторых потенциальных недостатках:

    Изменяемость — наши JavaBeans изменяемы из-за их методов установки — это может привести к проблемам параллелизма или согласованности Boilerplate — мы должны ввести геттеры для всех свойств и сеттеры для большинства, многое из этого может быть ненужным Конструктор с нулевым аргументом — нам часто нужны аргументы в наших конструкторах, чтобы гарантировать, что экземпляр объекта будет создан в допустимом состоянии, но стандарт JavaBean требует, чтобы мы предоставили конструктор с нулевым аргументом

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

5. Заключение

В этом руководстве мы сравнили POJO с JavaBeans.

Во-первых, мы узнали, что POJO — это объект Java, который не привязан ни к какой конкретной структуре, и что JavaBean — это особый тип POJO со строгим набором соглашений.

Затем мы увидели, как некоторые фреймворки и библиотеки используют соглашение об именах JavaBean для обнаружения свойств класса.

Как обычно, примеры доступны на GitHub.