Открыть сервис

POJO

POJO (Plain Old Java Object) — это термин, используемый в разработке программного обеспечения на языке Java для обозначения простого объекта, не привязанного к какой-либо специфической фреймворковой среде, наследованию от определённых классов или реализации обязательных интерфейсов. POJO представляет собой обычный Java-класс, который содержит поля, геттеры и сеттеры, а также, при необходимости, бизнес-логику, и не требует для своей работы наличия внешних библиотек или контейнеров.

История термина

Термин POJO был введён в обиход Мартином Фаулером, Ребеккой Парсонс и Джошем Маккензи в 2000 году. Они использовали его для противопоставления «тяжёлым» объектам, которые вынуждены были наследовать от специфических классов Java Enterprise Edition (J2EE), таких как javax.ejb.SessionBean или javax.servlet.http.HttpServlet. В то время разработка корпоративных приложений на Java была тесно связана с использованием EJB (Enterprise JavaBeans), что требовало от классов жёсткой привязки к контейнеру и реализации множества методов, не относящихся к бизнес-логике.

Фаулер и его коллеги стремились популяризировать подход, при котором основная часть кода приложения остаётся простой и тестируемой, а сложность контейнеров и фреймворков выносится на периферию. Термин быстро закрепился в сообществе Java-разработчиков и стал символом движения за упрощение архитектуры.

Определение и критерии

Не существует формальной спецификации, определяющей, что такое POJO. Однако на практике класс считается POJO, если он удовлетворяет следующим критериям:

  • Отсутствие наследования от предопределённых фреймворковых классов. Класс не должен расширять (extends) такие классы, как javax.servlet.http.HttpServlet, javax.ejb.SessionBean или com.opensymphony.xwork2.ActionSupport.
  • Отсутствие реализации обязательных интерфейсов. Класс не обязан реализовывать (implements) интерфейсы, навязанные фреймворком, например javax.ejb.EntityBean или java.io.Serializable (хотя реализация последнего часто допускается и не нарушает концепцию POJO, если она не является обязательным требованием для работы фреймворка).
  • Отсутствие привязки к специфическим аннотациям. Хотя современные фреймворки (например, Spring, Hibernate, JPA) активно используют аннотации, POJO может содержать их, но не должен быть обязан их иметь для своего функционирования. Аннотации в POJO обычно служат для метаданных, а не для изменения базового поведения объекта.
  • Возможность использования вне контейнера. POJO может быть создан и протестирован в обычной среде выполнения Java (JRE) без необходимости запуска сервера приложений или контейнера EJB.

Отличие от других понятий

POJO и JavaBeans

Термин JavaBean часто путают с POJO. JavaBean — это спецификация (Sun Microsystems, 1997), описывающая соглашения для повторно используемых компонентов. Основные требования к JavaBean:

  • Класс должен быть публичным.
  • Должен иметь конструктор без аргументов.
  • Доступ к свойствам осуществляется через геттеры и сеттеры, имена которых следуют определённому шаблону (например, getName(), setName(String name)).
  • Должен реализовывать интерфейс java.io.Serializable.

Таким образом, любой JavaBean является POJO, но не каждый POJO является JavaBean (например, POJO может не реализовывать Serializable или не иметь конструктора без аргументов).

POJO и DTO

DTO (Data Transfer Object) — это объект, предназначенный исключительно для передачи данных между слоями приложения или между процессами. DTO обычно не содержит бизнес-логики. POJO может выступать в роли DTO, но также может содержать и методы, реализующие бизнес-правила.

POJO и Entity (JPA)

В контексте Java Persistence API (JPA) Entity — это класс, который отображается на таблицу базы данных. Entity-класс является POJO, но он обязательно аннотируется @Entity и может содержать специфические аннотации для маппинга (@Table, @Column, @Id). Несмотря на это, базовый класс остаётся POJO, так как он не наследуется от фреймворковых классов (хотя некоторые реализации JPA могут требовать наследования от определённого базового класса, что нарушает концепцию POJO).

Преимущества использования POJO

  • Простота и читаемость. Код на основе POJO легче понимать, поддерживать и рецензировать, так как он не перегружен фреймворковой спецификой.
  • Тестируемость. POJO можно легко тестировать с помощью модульных тестов (JUnit) без необходимости запускать контейнер или эмулировать сложную инфраструктуру.
  • Независимость от фреймворка. POJO может быть использован в различных контекстах и с разными фреймворками. Один и тот же класс может быть одновременно использован как объект для Hibernate, как форма для Spring MVC и как DTO для веб-сервиса.
  • Гибкость. Разработчик может свободно проектировать класс, не ограничиваясь требованиями конкретного фреймворка. Это позволяет создавать более чистую объектно-ориентированную модель.
  • Снижение связанности. Приложение, построенное на POJO, менее связано с конкретными технологиями, что упрощает его миграцию и модернизацию.

Недостатки и критика

  • Отсутствие встроенной функциональности. POJO не предоставляет готовых сервисов, таких как управление транзакциями, безопасность или удалённый доступ. Всю эту инфраструктуру необходимо добавлять отдельно (например, с помощью аспектно-ориентированного программирования или конфигурации фреймворка).
  • Необходимость в связующем коде. Для интеграции POJO с фреймворками часто требуется написание дополнительного кода (конфигурационных файлов, фабрик, прокси-объектов). Однако современные фреймворки, такие как Spring, во многом автоматизируют этот процесс.
  • Риск «разбухания». В попытке сохранить класс «чистым» разработчики могут вынести всю логику в сервисные классы, оставив POJO лишь набором полей и геттеров/сеттеров, что приводит к анемичной модели предметной области. Этот антипаттерн критикуется сторонниками объектно-ориентированного подхода.

Применение в современных фреймворках

Несмотря на изначальное противопоставление фреймворкам, POJO стал основой многих современных Java-технологий:

  • Spring Framework. Ядро Spring построено на принципе управления POJO через Inversion of Control (IoC) контейнер. Spring Beans — это, по сути, POJO, которые конфигурируются и связываются контейнером.
  • Hibernate. ORM-фреймворк Hibernate позволяет маппить POJO на таблицы реляционной базы данных. Объекты, управляемые Hibernate, остаются POJO, хотя и требуют наличия конструктора без аргументов и некоторых аннотаций.
  • Java Persistence API (JPA). Стандарт JPA также ориентирован на работу с POJO, которые называются Entity.
  • Jackson и Gson. Библиотеки для сериализации/десериализации Java-объектов в JSON/XML работают с POJO, используя геттеры и сеттеры или аннотации для определения структуры данных.
  • Apache Struts 2. Действия (Actions) в Struts 2 являются POJO, что упрощает их тестирование и разработку по сравнению с предыдущей версией Struts 1.

Пример POJO

Ниже приведён простой пример класса, который является POJO:

```java public class Person { private String name; private int age;

public Person() { // Конструктор без аргументов }

public Person(String name, int age) { this.name = name; this.age = age; }

public String getName() { return name; }

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

public int getAge() { return age; }

public void setAge(int age) { this.age = age; }

// Метод, содержащий бизнес-логику public boolean isAdult() { return age >= 18; } } ```

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

Источники

  • Fowler, M. (2000). Refactoring: Improving the Design of Existing Code. Addison-Wesley.
  • Эванс, Э. (2006). Предметно-ориентированное проектирование (DDD): Структуризация сложных программных систем. Вильямс.
  • Oracle. JavaBeans Specification.
  • Spring Framework Documentation. The IoC Container.
  • Hibernate ORM Documentation. POJO vs. Dynamic Models.

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →