Другое

Maven dependencyManagement vs зависимости: Полное руководство

Узнайте ключевые различия между разделами dependencyManagement и dependencies в Maven. Изучите преимущества централизованного управления версиями и лучшие практики для многомодульных проектов.

В чём разница между dependencyManagement и dependencies в Maven? Я прочитал документацию Apache Maven и понимаю, что зависимости, определённые в dependencyManagement, могут использоваться в дочерних модулях без указания версии. Например, если родительский проект определяет зависимость в dependencyManagement:

xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8</version>
    </dependency>
 </dependencies>
</dependencyManagement>

Тогда в дочернем модуле можно сослаться на неё без указания версии:

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

Мой вопрос: необходимо ли определять зависимости в секции dependencyManagement родительского POM? В чём преимущества этого подхода по сравнению с прямым определением зависимостей в каждом модуле, где они требуются?

Основное различие между dependencyManagement и dependencies в Maven заключается в том, что dependencyManagement служит централизованным шаблоном для версий зависимостей между модулями, в то время как dependencies фактически включает зависимости в проект. С помощью dependencyManagement вы определяете версии один раз в родительском POM, и дочерние модули могут ссылаться на зависимости без указания версий, в то время как зависимости, определенные непосредственно в разделе dependencies, всегда наследуются дочерними модулями.

Содержание

Основные различия между dependencyManagement и dependencies

Фундаментальное различие между этими двумя разделами Maven заключается в их цели и поведении:

dependencyManagement действует как каталог версий:

  • Не автоматически включает зависимости в дочерние модули
  • Служит шаблоном для версионирования зависимостей
  • Дочерние модули могут ссылаться на зависимости без указания версий
  • Действует как механизм централизованного контроля версий

dependencies фактически включает зависимости:

  • Всегда наследуется дочерними модулями
  • Зависимости автоматически включаются в сборку
  • Дочерние модули получают эти зависимости если они не явно исключены

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

Важное различие: Артефакты, указанные в разделе <dependencies>, ВСЕГДА будут включены как зависимость дочернего модуля(ов), в то время как артефакты в <dependencyManagement> предоставляют только информацию о версиях, на которую могут ссылаться дочерние модули источник.

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

Централизованный контроль версий

Основное преимущество dependencyManagementцентрализованный контроль версий в мультимодульных проектах. Это обеспечивает согласованность и упрощает обновление версий:

  • Единая точка обслуживания: Обновляйте версии зависимостей в одном месте
  • Согласованные версии: Все модули автоматически используют одинаковые версии зависимостей
  • Сокращение дублирования: Избегайте повторения информации о версиях в нескольких файлах POM

Как отмечено в исследованиях, “зависимости, определенные в родительском pom с версией, переопределят версию, указанную в дочернем pom” источник.

Повышенная поддерживаемость

dependencyManagement значительно улучшает поддерживаемость проекта:

  • Более простые обновления версий: Обновляйте все зависимости в одном месте
  • Снижение дрейфа конфигурации: Минимизирует несоответствия версий между модулями
  • Упрощенное управление зависимостями: Дочерние модули сосредотачиваются на том, что им нужно, а не на версиях

Согласно Baeldung, это “помогает читаемости проекта и также делает его готовым для расширения до мультимодульной структуры”.

Улучшенная структура проекта

Для мультимодульных проектов dependencyManagement обеспечивает лучшую организацию:

  • Декуплирование: Разделяет объявление зависимостей от управления версиями
  • Гибкость: Дочерние модули могут переопределять версии при необходимости
  • Четкий намерение: Делает очевидным, какие зависимости фактически используются

Лучшие практики использования dependencyManagement

Централизуйте общие зависимости

Помещайте зависимости, которые используются в нескольких модулях, в раздел dependencyManagement родителя:

xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.7.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
    </dependency>
  </dependencies>
</dependencyManagement>

Минимизируйте прямые зависимости в родителе

Объявляйте прямые зависимости в разделе dependencies родителя только те, которые действительно нужны всем дочерним модулям:

Критическое предупреждение: “НЕ помещайте зависимость в родительский POM, которая не нужна каждому дочернему POM, и определенно не создавайте проект только для включения зависимостей” источник.

Используйте область импорта для BOM

При импорте спецификаций (Bill of Materials) используйте область import:

xml
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.7.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Переопределяйте версии при необходимости

Дочерние модули могут переопределять версии dependencyManagement, указывая свои собственные версии:

xml
<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>5.8.2</version> <!-- Переопределяет 4.13.2 из родителя -->
  </dependency>
</dependencies>

Примеры и реализация

Структура мультимодульного проекта

Рассмотрим типичную структуру мультимодульного проекта:

parent-pom/
├── pom.xml (родительский с dependencyManagement)
├── core/
│   └── pom.xml
├── web/
│   └── pom.xml
└── api/
    └── pom.xml

Конфигурация родительского POM

xml
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>multi-module-sample</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  
  <modules>
    <module>core</module>
    <module>web</module>
    <module>api</module>
  </modules>
  
  <dependencyManagement>
    <dependencies>
      <!-- Spring Boot BOM -->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.7.0</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      
      <!-- Общие зависимости фреймворка -->
      <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>5.8.2</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      
      <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

Конфигурация дочернего модуля

xml
<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.example</groupId>
    <artifactId>multi-module-sample</artifactId>
    <version>1.0.0</version>
  </parent>
  
  <artifactId>web-module</artifactId>
  
  <dependencies>
    <!-- Использует версию из dependencyManagement -->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Использует версию из dependencyManagement -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
    </dependency>
    
    <!-- Переопределяет версию из dependencyManagement -->
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <version>5.9.0</version>
    </dependency>
  </dependencies>
</project>

Распространенные ошибки, которых следует избегать

Определение зависимостей только в dependencyManagement

Одна из распространенных ошибок — “определение зависимости только в разделе dependencyManagement и без включения ее в тег dependencies” источник.

Неправильный подход:

xml
<!-- Родительский POM -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.13.2</version>
    </dependency>
  </dependencies>
</dependencyManagement>

Дочерний модуль НЕ получит junit, если не объявит его в своем собственном разделе dependencies.

Использование dependencyManagement для одно-модульных проектов

dependencyManagement предоставляет минимальные преимущества в одно-модульных проектах. Перегрузка поддержки отдельных разделов может не стоить того для простых проектов.

Игнорирование транзитивных зависимостей

Помните, что dependencyManagement влияет как на прямые, так и на транзитивные зависимости. “управление зависимостями имеет приоритет над посредничеством зависимостей для транзитивных зависимостей” источник.

Когда использовать каждый раздел

Используйте dependencyManagement, когда:

  • У вас есть мультимодульный проект
  • Вы хотите централизованный контроль версий
  • Несколько модулей используют одинаковые зависимости
  • Вам нужно управлять транзитивными зависимостями
  • Вы хотите импортировать BOM или каталоги зависимостей

Используйте dependencies, когда:

  • Вы хотите фактически включить зависимость в проект
  • Зависимость требуется всеми дочерними модулями
  • Вам нужно явно объявить зависимость, которую должны наследовать дочерние модули
  • Вы работаете с одно-модульным проектом

Сводная таблица

Аспект dependencyManagement dependencies
Цель Шаблоны контроля версий Фактическое включение зависимостей
Наследование Предоставляет информацию о версиях Всегда наследуется дочерними модулями
Использование дочерним модулем Ссылка без версии Автоматически включается
Лучше всего подходит для Мультимодульные проекты Общие зависимости для всех модулей
Поддержка Единая точка обновления версий Объявление для каждой зависимости

Заключение

dependencyManagement в Maven предоставляет мощные преимущества для управления сложными проектами:

  1. Централизованный контроль: Единое место для управления версиями зависимостей во всех модулях
  2. Согласованность: Обеспечивает использование одинаковых версий зависимостей во всех модулях
  3. Поддерживаемость: Упрощает обновления версий и снижает дрейф конфигурации
  4. Гибкость: Позволяет дочерним модулям переопределять версии при необходимости

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

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

Источники

  1. Maven dependencyManagement vs. dependencies Tags | Baeldung
  2. Introduction to the Dependency Mechanism – Maven
  3. Maven Dependencies vs DependencyManagement: Which One Should You Choose for Your Project?
  4. Maven - Dependencies vs DependencyManagement | Medium
  5. DependencyManagement vs Dependencies in Maven Projects
  6. Understanding Dependency Management in Maven - Part 2 | Medium
  7. Maven Dependency vs dependency management | Lekshmana Perumal Murugan
  8. Difference between Dependency Management and Dependencies in Maven | Horizn
  9. Maven multi-module: aggregate common dependencies in a single one? - Stack Overflow
  10. Maven Multi Module benefits over simple dependency - Stack Overflow
Авторы
Проверено модерацией
Модерация