Различия между зависимости и управлением в Maven

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

Например:

Родительский проект (Pro-par) определяет зависимость в dependencyManagement:

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

Тогда в потомке Pro-par я могу использовать junit:

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

Однако мне интересно, нужно ли определять junit в родительском pom? Почему бы не определить его непосредственно в нужном модуле?

Ответ 1

Управление зависимостями позволяет консолидировать и централизовать управление версиями зависимостей без добавления зависимостей, которые унаследованы всеми дочерними элементами. Это особенно полезно, если у вас есть набор проектов (т.е. Более одного), который наследует общий родительский элемент.

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

Ответ 2

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

В родительском POM основное различие между <dependencies> и <dependencyManagement> таково:

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

Артефакты, указанные в разделе <dependencyManagement>, будут включены только в дочерний модуль, если они также были указаны в разделе <dependencies> самого дочернего модуля, Почему ты хорошо спрашиваешь? потому что вы указываете версию и/или область действия в родительском объекте, и вы можете оставить их при указании зависимостей в дочернем POM. Это может помочь вам использовать унифицированные версии для зависимостей для дочерних модулей, не указывая версию в каждом дочернем модуле.

Ответ 3

Документация на сайте Maven ужасна. Взаимодействие dependencyManagement просто переносит ваши определения зависимостей (версия, исключения и т.д.) До родительского пом, а затем в детские помпы вам просто нужно поставить groupId и artifactId. То, что это (за исключением родительских цепочек жучков и т.п., Но это не очень сложно) - dependencyManagement выигрывает над зависимостями на родительском уровне - но если у вас есть вопрос об этом или в импорте, то в документации Maven немного лучше).

После прочтения всех мусора "a", "b", "c" на сайте Maven и запутывания я переписал их пример. Итак, если у вас есть 2 проекта (proj1 и proj2), которые имеют общую зависимость (betaShared), вы можете переместить эту зависимость до родительского пом. Пока вы на нем, вы также можете перемещать любые другие зависимости (альфа и чарли), но только если это имеет смысл для вашего проекта. Итак, для ситуации, изложенной в предыдущих предложениях, вот решение с зависимостью управления в родительском pom:

<!-- ParentProj pom -->
<project>
  <dependencyManagement>
    <dependencies>
      <dependency> <!-- not much benefit defining alpha here, as we only use in 1 child, so optional -->
        <groupId>alpha</groupId>
        <artifactId>alpha</artifactId>
        <version>1.0</version>
        <exclusions>
          <exclusion>
            <groupId>zebra</groupId>
            <artifactId>zebra</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>charlie</groupId> <!-- not much benefit defining charlie here, so optional -->
        <artifactId>charlie</artifactId>
        <version>1.0</version>
        <type>war</type>
        <scope>runtime</scope>
      </dependency>
      <dependency> <!-- defining betaShared here makes a lot of sense -->
        <groupId>betaShared</groupId>
        <artifactId>betaShared</artifactId>
        <version>1.0</version>
        <type>bar</type>
        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
</project>

<!-- Child Proj1 pom -->
<project>
  <dependencies>
    <dependency>
      <groupId>alpha</groupId>
      <artifactId>alpha</artifactId>  <!-- jar type IS DEFAULT, so no need to specify in child projects -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId>
      <artifactId>betaShared</artifactId>
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>

<!-- Child Proj2 -->
<project>
  <dependencies>
    <dependency>
      <groupId>charlie</groupId>
      <artifactId>charlie</artifactId>
      <type>war</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
    <dependency>
      <groupId>betaShared</groupId> 
      <artifactId>betaShared</artifactId> 
      <type>bar</type> <!-- This is not a jar dependency, so we must specify type. -->
    </dependency>
  </dependencies>
</project>

Ответ 4

Как ты сказал; dependencyManagement используется для вывода всей информации о зависимостях в общий файл POM, что упрощает ссылки в дочернем POM файле.

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

Наконец, dependencyManagement можно использовать для определения стандартной версии артефакта для использования в нескольких проектах.

Ответ 5

Там еще одна вещь, которая недостаточно выделена, на мой взгляд, и это нежелательное наследование.

Вот дополнительный пример:

Я заявляю в моем parent пом:

<dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
</dependencies>

бум! У меня есть это в моих модулях Child A, Child B и Child C:

  • Причастность, унаследованная от детских помпонов
  • Единственное место для управления
  • Не нужно что-либо переопределять в детских помпонах
  • Я все еще могу redelcare и переопределить до version 18.0 в Child B если я хочу.

Но что, если мне не понадобится гуава в Child C и ни в будущих модулях Child D и Child E?

Они все еще унаследуют это, и это нежелательно! Это похоже на запах кода Java God Object, где вы наследуете некоторые полезные биты из класса, а также массу нежелательных вещей.

Это где <dependencyManagement> вступает в игру. Когда вы добавляете это в родительский pom, все ваши дочерние модули перестают его видеть. И, таким образом, вы вынуждены заходить в каждый отдельный модуль, который ему нужен, и объявлять его снова (хотя Child A и Child B, без версии).

И, очевидно, вы не делаете это для Child C, и, следовательно, ваш модуль остается скудным.

Ответ 6

Существует несколько ответов, в которых описываются различия между <depedencies> и <dependencyManagement> с maven.

Тем не менее, несколько пунктов разработаны ниже в сжатой форме:

  1. <dependencyManagement> позволяет консолидировать все зависимости (используемые на уровне дочернего pom), используемые в разных модулях - ясность, централизованное управление версиями зависимостей.
  2. <dependencyManagement> позволяет легко обновлять/понижать зависимости в зависимости от необходимости, в другом случае это необходимо выполнять на каждом дочернем уровне - согласованность
  3. зависимости, предоставленные в <dependencies> всегда импортируются, в то время как зависимости, предоставленные в <dependencyManagement> в родительском pom, будут импортированы, только если дочерний pom имеет соответствующую запись в своем <dependencies>.

Ответ 7

Если зависимость была определена в элементе управления приоритетом pom верхнего уровня, дочернему проекту не нужно явно указывать версию зависимости. если дочерний проект действительно определил версию, он переопределит версию, указанную на верхнем уровне Раздел управления зависимостями POMs. То есть, версия зависимости зависит только от используется, когда ребенок не объявляет версию напрямую.

Ответ 8

Извините, я очень поздно на вечеринку.

Позвольте мне попытаться объяснить разницу, используя mvn dependency:tree

Рассмотрим пример ниже

Parent POM - мой проект

<modules>
    <module>app</module>
    <module>data</module>
</modules>

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>19.0</version>
    </dependency>
</dependencies>

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

Детский POM - модуль данных

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

Дочерний POM - модуль приложения (не имеет дополнительных зависимостей, поэтому оставляя зависимости пустыми)

 <dependencies>
</dependencies>

mvn dependency:tree команду mvn dependency:tree, мы получим следующий результат

Scanning for projects...
------------------------------------------------------------------------
Reactor Build Order:

MyProject
app
data

------------------------------------------------------------------------
Building MyProject 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ MyProject ---
com.iamvickyav:MyProject:pom:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building app 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ app ---
com.iamvickyav:app:jar:1.0-SNAPSHOT
\- com.google.guava:guava:jar:19.0:compile

------------------------------------------------------------------------
Building data 1.0-SNAPSHOT
------------------------------------------------------------------------

--- maven-dependency-plugin:2.8:tree (default-cli) @ data ---
com.iamvickyav:data:jar:1.0-SNAPSHOT
+- org.apache.commons:commons-lang3:jar:3.9:compile
\- com.google.guava:guava:jar:19.0:compile

Google guava указан как зависимость в каждом модуле (включая родительский), в то время как Apache Commons указан как зависимость только в модуле данных (даже в родительском модуле)

Ответ 9

В родительском POM основное различие между <dependencies> и <dependencyManagement> заключается в следующем:

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

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

Ответ 10

В Eclipse есть еще одна функция в dependencyManagement. Когда dependencies используется без него, в файле pom замечены необоснованные зависимости. Если используется dependencyManagement, нерешенные зависимости остаются незаметными в файле pom, и ошибки появляются только в java файлах. (импорт и т.д.)

Ответ 11

Разница между ними лучше всего заключается в том, что кажется необходимым и достаточным определением элемента dependencyManagement, доступного в документах веб-сайта Maven:

dependencyManagement

"Информация о зависимостях по умолчанию для проектов, которые наследуются от этого. Зависимости в этом разделе не разрешаются сразу. Вместо этого, когда POM, производное от этого, объявляет зависимость, описанную соответствующими groupId и artifactId, версия и другие значения из этого раздела используются для этой зависимости, если они еще не были указаны ". [ https://maven.apache.org/ref/3.6.1/maven-model/maven.html ]

Его следует прочитать вместе с дополнительной информацией, доступной на другой странице:

'... минимальный набор информации для сопоставления ссылки зависимости с разделом dependencyManagement на самом деле является {groupId, artifactId, type, classifier}. Во многих случаях эти зависимости будут ссылаться на артефакты jar без классификатора. Это позволяет нам сокращать идентификатор, установленный на {groupId, artifactId}, поскольку по умолчанию для поля типа используется jar, а классификатор по умолчанию - null. ' [https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html ]

Таким образом, все подэлементы (область действия, исключения и т.д.) Элемента зависимости - кроме groupId, artifactId, типа, классификатора, а не только версии - доступны для блокировки/дефолта в точке (и, таким образом, наследуются от там далее) вы указываете зависимость внутри dependencyElement. Если вы указали зависимость с подэлементами типа и классификатора (см. первую цитируемую веб-страницу, чтобы проверить все подэлементы) как не jar и не null соответственно, вам нужно {groupId, artifactId, классификатор, тип} для ссылки (разрешения) ) эта зависимость в любой точке наследования, происходящая из элемента dependencyManagement. Иначе, {groupId, artifactId} будет достаточно, если вы не собираетесь переопределять значения по умолчанию для классификатора и типа (jar и null соответственно). Так что по умолчанию это хорошее ключевое слово в этом определении; любой подэлемент (кроме groupId, artifactId, классификатор и тип, разумеется) явно присваивает значение (я) в точке, где вы ссылаетесь на зависимость, переопределяет значения по умолчанию в элементе dependencyManagement.

Таким образом, любой элемент зависимостей за пределами dependencyManagement, будь то ссылка на какой-либо элемент dependencyManagement или автономный, немедленно разрешается (то есть устанавливается в локальный репозиторий и доступен для путей к классам).

Ответ 12

Если у вас есть тестовые примеры JUnit, определенные во всех дочерних модулях, и вы используете STS или eclipse, то при простом определении eclipse выдаст ошибки для тестовых случаев.

Вам нужно добавить зависимости для внешнего тега junit в родительском модуле, чтобы вы не получали ошибок для тестовых примеров в eclipse. Хотя maven все равно будет компилироваться без такого тэга