Java for Beginner
675 subscribers
559 photos
156 videos
12 files
858 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Руководство по POM (Project Object Model) в Maven

POM (Project Object Model) является основой любого Maven-проекта. Файл pom.xml определяет структуру проекта, его зависимости, процесс сборки и другие аспекты, необходимые для управления жизненным циклом проекта. Этот документ представляет собой XML-файл, который Maven интерпретирует для создания модели проекта в памяти.


Основные теги

Основные теги pom.xml формируют базовую идентификацию и структуру проекта. Они обязательны или критически важны для корректной работы Maven.

<project>: Корневой элемент каждого pom.xml. Он определяет пространство имен XML (xmlns) и схему (xsi:schemaLocation), чтобы Maven мог валидировать файл. Все остальные элементы являются дочерними для <project>. В памяти Maven создает объект Project, который хранит всю информацию о проекте, включая зависимости, плагины и настройки сборки.
<modelVersion>: Указывает версию модели POM, используемой в файле. На момент 2025 года стандартной является версия 4.0.0. Этот тег необходим, так как Maven использует его для определения правил парсинга и совместимости. Неправильная версия приведет к ошибке парсинга.
<groupId>: Уникальный идентификатор группы, к которой относится проект. Обычно это доменное имя компании или организации в обратном порядке (например, com.example). В памяти Maven использует groupId как часть координат для идентификации артефакта в репозитории.
<artifactId>: Уникальное имя артефакта внутри группы. Это название проекта или модуля (например, my-app). Вместе с groupId и version формирует уникальные координаты артефакта.
<version>: Версия проекта. Следует семантическому версионированию (например, 1.0.0-SNAPSHOT). Maven использует версию для управления артефактами в локальном и удаленных репозиториях. Суффикс SNAPSHOT указывает на нестабильную версию, что влияет на поведение кэширования.
<packaging>: Определяет тип выходного артефакта (например, jar, war, pom). По умолчанию — jar. Этот тег влияет на жизненный цикл сборки, так как Maven выбирает соответствующие плагины и цели (goals) для обработки. Например, для war подключается плагин maven-war-plugin.

Эти теги формируют минимальный pom.xml. Maven парсит их в объектную модель, которая хранится в памяти JVM во время выполнения. Объектная модель включает org.apache.maven.model.Model, где каждый тег маппится на соответствующее поле или коллекцию. Например, groupId, artifactId и version объединяются в уникальный ключ артефакта.


Расширенные теги

Расширенные теги добавляют метаданные, улучшающие документацию и управление проектом. Они необязательны, но полезны в корпоративных средах.

<name>: Человекочитаемое название проекта. Используется в отчетах и документации, генерируемых Maven (например, через maven-site-plugin). Не влияет на логику сборки, но хранится в метаданных артефакта.
<description>: Описание проекта. Как и <name>, используется для документации. Maven включает это поле в метаданные артефакта, которые публикуются в репозиторий.

<url>: URL проекта, например, сайт или репозиторий. Используется в документации и для генерации ссылок в отчетах.

<inceptionYear>: Год создания проекта. Это поле чисто информационное, хранится в метаданных.

<organization>: Содержит информацию об организации, включая <name> и <url>. Используется для единообразной документации в крупных проектах.

Эти теги не влияют на процесс сборки, но добавляются в файл метаданных артефакта (META-INF/maven/groupId/artifactId/pom.properties), который создается при упаковке. В памяти они хранятся как часть объекта Model, но не участвуют в логике выполнения.

#Java #middle #Maven #pom
Работа с <properties>

Тег <properties> позволяет определять пользовательские переменные, которые можно использовать в других частях pom.xml. Это улучшает читаемость и упрощает управление конфигурацией.

Пример:
<properties>
<java.version>11</java.version>
<spring.version>5.3.10</spring.version>
</properties>


Переменные используются через синтаксис ${property.name}.

Например:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>


Maven при парсинге pom.xml заменяет все ${...} на соответствующие значения. Это происходит на этапе создания модели в памяти. Если свойство не найдено, Maven пытается использовать системные свойства JVM или переменные окружения. Если и это не удается, сборка завершится ошибкой.

Свойства также могут быть переопределены через командную строку:
mvn clean install -Djava.version=17


В памяти свойства хранятся в объекте Properties внутри модели Model. Они доступны всем плагинам и процессам сборки.
Важный нюанс: свойства не наследуются автоматически в дочерних модулях, если они определены в <properties> родительского POM. Для этого нужно использовать <dependencyManagement> или <pluginManagement>.


<dependencies>: Управление зависимостями

Тег <dependencies> определяет библиотеки, необходимые проекту. Каждая зависимость описывается тегом <dependency> с обязательными полями groupId, artifactId и version.

Scope'ы зависимостей

Атрибут <scope> определяет область применения зависимости:
compile: Зависимость доступна для компиляции, тестирования и выполнения. Включается в итоговый артефакт (например, в jar). Это значение по умолчанию.
provided: Зависимость нужна для компиляции, но предоставляется средой выполнения (например, сервлет API в контейнере). Не включается в итоговый артефакт.
runtime: Зависимость нужна только во время выполнения (например, JDBC-драйвер). Не используется при компиляции.
test: Зависимость нужна только для тестирования (например, JUnit). Не включается в итоговый артефакт.
system: Указывает локальный путь к зависимости через <systemPath>. Используется редко, так как нарушает принцип переносимости.
import: Используется в <dependencyManagement> для импорта зависимостей из другого POM. Не добавляет зависимость напрямую.


Maven при разрешении зависимостей создает граф зависимостей в памяти (используя org.apache.maven.artifact.Artifact). Для каждого артефакта хранится его scope, что влияет на classpath для различных фаз сборки. Например, test зависимости добавляются только в classpath для фазы test.

Exclusions и конфликт зависимостей

Конфликты зависимостей возникают, когда разные версии одной и той же библиотеки включаются через транзитивные зависимости. Maven решает конфликты, выбирая ближайшую к корню графа версию (стратегия "nearest wins"). Это может привести к проблемам, если выбранная версия несовместима.

Для исключения нежелательных транзитивных зависимостей используется тег <exclusions>:
<dependency>
<groupId>org.example</groupId>
<artifactId>lib-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>org.unwanted</groupId>
<artifactId>unwanted-lib</artifactId>
</exclusion>
</exclusions>
</dependency>


В памяти Maven модифицирует граф зависимостей, удаляя исключенные артефакты. Это происходит на этапе разрешения зависимостей (dependency:resolve).

Для диагностики конфликтов полезна команда:
mvn dependency:tree


#Java #middle #Maven #pom
<dependencyManagement>: Централизованный контроль зависимостей

Тег <dependencyManagement> позволяет определять версии и настройки зависимостей, которые будут использоваться в проекте или его модулях. Это особенно полезно в многомодульных проектах.

Пример:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.10</version>
</dependency>
</dependencies>
</dependencyManagement>


Зависимости из <dependencyManagement> не добавляются в проект автоматически. Они активируются только при указании groupId и artifactId в <dependencies> без версии. Это позволяет централизовать управление версиями в родительском POM.
В памяти Maven хранит эти зависимости в объекте DependencyManagement, который используется для разрешения версий при парсинге дочерних POM. Это снижает риск конфликтов версий в многомодульных проектах.
<build> и <plugins>
Тег <build> определяет процесс сборки проекта. Он включает настройки каталогов, плагинов и другие параметры.


Основные дочерние элементы:
<sourceDirectory>: Путь к исходному коду (по умолчанию src/main/java).
<testSourceDirectory>: Путь к тестам (по умолчанию src/test/
java).
<resources>: Ресурсы, включаемые в артефакт.
<plugins>: Список плагинов для выполнения задач.


Пример плагина:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>


Каждый плагин привязан к фазам жизненного цикла Maven (например, compile, test, package). Плагины выполняются в JVM как отдельные классы, загружаемые через собственный класслоадер Maven. В памяти создается объект Plugin, содержащий конфигурацию и привязки к фазам.
Тег <pluginManagement> работает аналогично <dependencyManagement>, позволяя задавать конфигурацию плагинов для наследования в дочерних модулях.



<profiles>: Профили сборки

Профили позволяют настраивать сборку под разные окружения (например, dev, prod). Тег <profiles> содержит список <profile>.

Пример:
<profiles>
<profile>
<id>dev</id>
<properties>
<env>development</env>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<env>production</env>
</properties>
</profile>
</profiles>


Профиль активируется через:
Командную строку: mvn clean install -Pdev.
Условия в <activation> (например, по OS, JDK или наличию файла).


Maven при парсинге объединяет активный профиль с основным pom.xml. Это происходит в памяти, где профиль мержится с моделью Model. Если несколько профилей активны, они применяются в порядке определения.
<repositories> и <pluginRepositories>

Теги <repositories> и <pluginRepositories> указывают, где Maven должен искать зависимости и плагины. По умолчанию используется центральный репозиторий Maven (https://repo.maven.apache.org/maven2).

Пример:
<repositories>
<repository>
<id>custom-repo</id>
<url>https://repo.example.com</url>
</repository>
</repositories>


Maven загружает артефакты сначала из локального репозитория (~/.m2/repository), затем из указанных репозиториев. В памяти создается список объектов Repository, которые используются резолвером зависимостей.

#Java #middle #Maven #pom
Parent POM'ы и наследование

Родительский POM позволяет централизовать конфигурацию для нескольких проектов.

Дочерний проект ссылается на родительский через <parent>:
<parent>
<groupId>com.example</groupId>
<artifactId>parent-project</artifactId>
<version>1.0</version>
</parent>


Maven при парсинге загружает родительский POM и объединяет его с дочерним.

Наследуются:
- <dependencyManagement> и <pluginManagement>.
- <properties>.
- <repositories> и <pluginRepositories>.

В памяти создается композитная модель Model, где дочерний POM имеет приоритет над родительским. Это позволяет переопределять настройки. Однако <dependencies> и <plugins> не наследуются напрямую, чтобы избежать нежелательных включений.


Нюансы работы в памяти

Maven при запуске создает в JVM объектную модель проекта:
Парсинг pom.xml с помощью библиотеки plexus-utils и создание объекта org.apache.maven.model.Model.
Разрешение переменных ${...} с учетом <properties>, системных свойств и окружения.
Построение графа зависимостей с использованием Aether (библиотека для работы с репозиториями).
Создание плана выполнения (execution plan), где плагины привязываются к фазам жизненного цикла.


Каждый плагин выполняется в изолированном класслоадере, чтобы избежать конфликтов зависимостей. Локальный репозиторий (~/.m2/repository) кэширует артефакты, минимизируя сетевые запросы. Для SNAPSHOT-версий Maven периодически проверяет обновления в удаленных репозиториях.



#Java #middle #Maven #Pom