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

9 ответов


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

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


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

в Родительском пом, основное различие между <dependencies> и <dependencyManagement> это:

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

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


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

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

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


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

прочитав весь мусор "a", "b", " c " на сайте Maven и запутавшись, я переписал их пример. Поэтому, если у вас есть 2 проекта (proj1 и proj2), которые имеют общую зависимость (betaShared), вы можете переместить эту зависимость до родительского pom. Пока вы на нем, вы также можете переместить любые другие зависимости (alpha и charlie), но только если это имеет смысл для вашего проекта. Итак, для ситуации, описанной в предыдущих предложениях, вот решение с dependencyManagement в Родительском 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>

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

вот поэтапный пример:

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

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

бум! Он у меня в Child A, Child B и Child C модули:

  • Implicilty наследуется ребенком помпоны
  • одно место для управления
  • нет необходимости объявлять что-либо в ребенке poms
  • я все еще могу redelcare и переопределить на version 18.0 на Child B Если я хочу.

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

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

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

и, очевидно, вы не делаете это для Child C, и, таким образом, ваш модуль остается худой.


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


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

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

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

в Родительском пом, основное различие между <dependencies> и <dependencyManagement> это:

артефакты, указанные в <dependencies> раздел всегда будет включен в качестве зависимости от дочерних модулей.

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


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