Этот вопрос проверяет понимание механизмов разрешения конфликтов версий зависимостей в Maven, что критически важно для стабильности сборки и предотвращения ошибок NoSuchMethodError или ClassNotFoundException.
Maven автоматически управляет транзитивными зависимостями, но когда разные модули требуют разные версии одной библиотеки, возникает конфликт. Maven разрешает его по определённым правилам, и понимание этих правил позволяет контролировать итоговый classpath.
Разработчики могут активно управлять версиями, а не полагаться только на автоматику Maven.
<dependencyManagement>. Это гарантирует использование единой версии во всех модулях.Представьте, что ваш проект зависит от библиотек lib-A:1.0 и lib-B:2.0, и обе они транзитивно требуют commons-io, но разные версии: 2.5 и 2.6 соответственно.
<dependencies>
<!-- lib-A объявлена первой и приносит commons-io:2.5 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-A</artifactId>
<version>1.0</version>
</dependency>
<!-- lib-B объявлена второй и приносит commons-io:2.6 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-B</artifactId>
<version>2.0</version>
</dependency>
</dependencies>По правилу первого объявления будет использована commons-io:2.5. Чтобы явно выбрать версию 2.6, можно добавить прямое объявление зависимости или использовать exclusion.
<!-- Способ 1: Явное объявление (переопределит транзитивную) -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<!-- Способ 2: Исключение нежелательной транзитивной зависимости -->
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-A</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</exclusion>
</exclusions>
</dependency>Команды Maven помогают визуализировать дерево зависимостей и найти конфликты:mvn dependency:tree — показывает полное дерево.mvn dependency:tree -Dverbose — выделяет конфликты (показывает, где версии были опущены).mvn dependency:analyze — анализирует объявленные и используемые зависимости.
Вывод: Используйте <dependencyManagement> для централизованного контроля версий в многомодульных проектах, а <exclusions> — для точечного удаления проблемных транзитивных зависимостей. Регулярный анализ дерева зависимостей помогает предотвратить скрытые конфликты, ведущие к ошибкам времени выполнения.