Перейти к основному содержимому

Maven dependencyManagement и зависимости Tags

· 5 мин. чтения

1. Обзор

В этом руководстве мы рассмотрим два важных тега MavendependencyManagement и dependencies .

Эти функции особенно полезны для многомодульных проектов.

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

2. Использование

Как правило, мы используем тег dependencyManagement , чтобы избежать повторения тегов версии и области действия , когда мы определяем наши зависимости в теге зависимостей . Таким образом, требуемая зависимость объявляется в центральном файле POM.

2.1. Управление зависимостями

Этот тег состоит из тега зависимостей , который может содержать несколько тегов зависимостей . Каждая зависимость должна иметь как минимум три основных тега: groupId , ArtifactId и version . Давайте посмотрим пример:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
</dependencyManagement>

Приведенный выше код просто объявляет новый артефакт commons-lang3 , но на самом деле он не добавляет его в список ресурсов зависимостей проекта.

2.2. зависимости

Этот тег содержит список тегов зависимостей . Каждая зависимость должна иметь как минимум два основных тега: groupId и ArtiftId .

Давайте посмотрим на быстрый пример:

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>

Теги версии и области действия могут наследоваться неявно, если мы использовали тег dependencyManagement ранее в файле POM :

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>

3. Сходства

Оба этих тега предназначены для объявления какой-либо сторонней зависимости или зависимости от подмодуля. Они дополняют друг друга.

На самом деле мы обычно определяем тег dependencyManagement один раз, перед тегом зависимостей . Это используется для объявления зависимостей в файле POM. Это объявление является просто объявлением, и на самом деле оно не добавляет зависимости в проект.

Давайте посмотрим на пример добавления зависимости библиотеки JUnit:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

Как мы видим в приведенном выше коде, есть тег dependencyManagement , который сам содержит другой тег зависимостей .

Теперь давайте посмотрим на другую сторону кода, которая добавляет фактическую зависимость в проект:

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>

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

Одни и те же теги groupId и ArtiftId повторяются в обоих фрагментах кода, и между ними существует значимая корреляция: оба они относятся к одному и тому же артефакту.

Как мы видим, в нашем более позднем теге зависимости нет никакого тега версии . Удивительно, но это корректный синтаксис, и его можно без проблем разобрать и скомпилировать. Причину легко догадаться: будет использоваться версия, объявленная dependencyManagement .

4. Отличия

4.1. Структурная разница

Как мы уже говорили ранее, основное структурное различие между этими двумя тегами заключается в логике наследования. Мы определяем версию в теге dependencyManagement , а затем можем использовать указанную версию, не указывая ее в следующем теге зависимостей .

4.2. Поведенческая разница

dependencyManagement — это просто объявление, и на самом деле оно не добавляет зависимости. Объявленные зависимости в этом разделе должны быть позже использованы тегом зависимостей . Это просто тег зависимостей , который вызывает реальную зависимость. В приведенном выше примере тег dependencyManagement не добавит библиотеку junit ни в какую область. Это просто объявление тега будущих зависимостей .

5. Реальный пример

Почти все проекты с открытым исходным кодом на основе Maven используют этот механизм.

Давайте посмотрим на пример из самого проекта Maven . Мы видим зависимость hamcrest-core , которая существует в проекте Maven. Сначала он объявляется в теге dependencyManagement , а затем импортируется основным тегом зависимостей :

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>2.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

6. Распространенные варианты использования

Очень распространенный вариант использования этой функции — многомодульный проект.

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

Простым решением этой проблемы, безусловно, является использование тега dependencyManagement в корневом файле POM (обычно называемом «родительским»), а затем использование зависимостей в дочерних файлах POM (подмодулях) и даже в самом родительском модуле (если применимо). .

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

7. Распространенные ошибки

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

Давайте посмотрим пример:

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
...
</dependencies>
</dependencyManagement>

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

import org.apache.commons.lang3.StringUtils;

public class Main {

public static void main(String[] args) {
StringUtils.isBlank(" ");
}
}

Этот код не будет компилироваться из-за отсутствия библиотеки. Компилятор жалуется на ошибку:

[ERROR] Failed to execute goal compile (default-compile) on project sample-module: Compilation failure
[ERROR] ~/sample-module/src/main/java/com/foreach/Main.java:[3,32] package org.apache.commons.lang3 does not exist

Чтобы избежать этой ошибки, достаточно добавить приведенный ниже тег зависимостей в файл POM подмодуля:

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
</dependencies>

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

В этом руководстве мы сравнили теги dependencyManagement и зависимостей Maven. Затем мы рассмотрели их сходства и различия и увидели, как они работают вместе.

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