Различия между зависимости и управлением в Maven - PullRequest
628 голосов
/ 12 апреля 2010

В чем разница между 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? Почему бы не определить его непосредственно в нужном модуле?

Ответы [ 10 ]

598 голосов
/ 17 мая 2016

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

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

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

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

397 голосов
/ 12 апреля 2010

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

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

44 голосов
/ 26 марта 2016

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

Прочитав весь мусор 'a', 'b', 'c' на сайте Maven и запутавшись, я переписал их пример. Таким образом, если у вас есть 2 проекта (proj1 и proj2), которые имеют общую зависимость (betaShared), вы можете переместить эту зависимость до родительского pom. Пока вы занимаетесь этим, вы также можете перемещать любые другие зависимости (альфа и чарли), но только если это имеет смысл для вашего проекта. Таким образом, для ситуации, изложенной в предыдущих предложениях, вот решение с зависимостьюManagement в родительском 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>
43 голосов
/ 12 апреля 2010

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

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

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

30 голосов
/ 17 декабря 2017

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

Вот пример:

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

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

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

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

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

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

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

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

14 голосов
/ 18 апреля 2017

Есть несколько ответов о различиях между тегами <depedencies> и <dependencyManagement> с maven.

Однако, несколько пунктов, кратко изложенных ниже:

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

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

4 голосов
/ 10 января 2018

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

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

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

2 голосов
/ 19 июня 2019

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

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

Рассмотрим приведенный ниже пример

Родительский 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>

Child POM - модуль данных

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

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

 <dependencies>
</dependencies>

При выполнении команды 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 указан как зависимость только в модуле данных (даже в родительском модуле)

1 голос
/ 19 декабря 2013

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...