Что такое конфликт зависимостей (dependency conflict) в Maven/Gradle?

Ответ

Конфликт зависимостей — это ситуация, когда разные библиотеки (транзитивные зависимости) требуют несовместимые версии одной и той же библиотеки, и система сборки не может автоматически выбрать, какую версию использовать.

Пример в Maven POM:

<!-- Библиотека A транзитивно требует commons-lang:2.5 -->
<dependency>
    <groupId>com.example</groupId>
    <artifactId>lib-a</artifactId>
    <version>1.0</version>
</dependency>

<!-- Библиотека B транзитивно требует commons-lang:3.0 -->
<dependency>
    <groupId>com.example</groupId>
    <artifactId>lib-b</artifactId>
    <version>2.0</version>
</dependency>

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

Способы разрешения:

  1. Явное указание версии (Maven): В секции <dependencyManagement> или прямо в <dependency>.

    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>3.12.0</version> <!-- Форсируем конкретную версию -->
    </dependency>
  2. Исключение транзитивной зависимости (Maven):

    <dependency>
        <groupId>com.example</groupId>
        <artifactId>lib-a</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
  3. Анализ дерева зависимостей:

    mvn dependency:tree -Dincludes=commons-lang
    # или в Gradle
    gradle dependencies

В Gradle конфликты часто решаются с помощью resolutionStrategy в build.gradle.

Ответ 18+ 🔞

Да ты посмотри, какая хуйня случается! Конфликт зависимостей, ёпта! Это когда твои библиотеки, как пьяные бабы на танцполе, начинают орать каждая про свою версию одной и той же хрени. Система сборки смотрит на это безобразие и просто встаёт в ступор — какую, нахуй, версию тащить-то? Обе хотят, а они несовместимые, как кошка с собакой!

Вот смотри, как это в Maven POM выглядит, реальный пиздец:

<!-- Библиотека A тащит за собой старьё, commons-lang:2.5 -->
<dependency>
    <groupId>com.example</groupId>
    <artifactId>lib-a</artifactId>
    <version>1.0</version>
</dependency>

<!-- А эта, сука, Библиотека B, уже требует новую, commons-lang:3.0 -->
<dependency>
    <groupId>com.example</groupId>
    <artifactId>lib-b</artifactId>
    <version>2.0</version>
</dependency>

Maven, такой хитрожопый, по умолчанию берёт ту версию, которая в дереве зависимостей ближе всего к корню сидит. Правило "nearest definition", блядь. Но это не всегда спасает, овердохуища проблем всё равно вылазят.

Ну и как из этой жопы вылезать? А вот как, слушай сюда:

  1. Впендюрить свою версию, чтоб все заткнулись (Maven): В <dependencyManagement> или прямо в зависимость пишешь, какая тебе нужна. Все остальные — идут лесом.

    <dependency>
        <groupId>commons-lang</groupId>
        <artifactId>commons-lang</artifactId>
        <version>3.12.0</version> <!-- Вот тебе, сука, новая версия, и не спорь! -->
    </dependency>
  2. Выпилить ненужную транзитивную хрень нахуй (Maven): Говоришь одной библиотеке: "Слушай, дружок, а свой commons-lang ты оставь при себе, я свой принёс".

    <dependency>
        <groupId>com.example</groupId>
        <artifactId>lib-a</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <groupId>commons-lang</groupId>
                <artifactId>commons-lang</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
  3. Сначала разобраться, кто тут вообще серит (Анализ дерева): Прежде чем рубить с плеча, посмотри, что за мудаки у тебя в проекте и кто что тянет.

    mvn dependency:tree -Dincludes=commons-lang
    # или в Gradle, там команда своя
    gradle dependencies

    Это как карта местности перед боем, блядь. Без неё — слепой в жопу лезешь.

А в Gradle, там свои приколы, но тоже решаемо. Там можно в build.gradle накрутить resolutionStrategy и всем этим спорщикам мозги прописать, какую версию использовать. В общем, варианты есть, главное — не паниковать, а разбираться, что за пиздопроебибна у тебя в зависимостях творится.