Объявить зависимость в разделе ‹dependencyManagement›, даже если зависимость не используется везде?

Мы используем maven 2.1.0. У меня есть несколько модулей, которые полностью разделены, но все же имеют много общих зависимостей. Подобно log4J, но некоторым модулям он не нужен. Мне интересно, стоит ли объявить все общие зависимости в одном родительском файле в разделе <dependencyManagement> или есть лучший способ справиться с этим?

Следующий вопрос о <dependencyManagement>. Если я объявлю Log4J в разделе <dependencyManagement> родительского объекта и подпроект не будет его использовать, будет ли он включен в любом случае?


person Mike Pone    schedule 28.05.2009    source источник
comment
Провалите @Kieveli за бесполезный бесполезный ответ.   -  person Jherico    schedule 28.05.2009
comment
Я думаю, что общие / общие зависимости обязательно должны быть настроены в разделе dependencyManagement. Вопрос в том, не следует ли, пройдя по этому пути, добавлять все зависимости (общие или нет) в dependencyManagement. Я вижу плюсы и минусы обоих. Какие-нибудь лучшие практики для этого?   -  person Hardy    schedule 09.12.2009


Ответы (6)


Каждый модуль должен иметь свой собственный POM и объявлять свои зависимости. Это не только отслеживает внешние зависимости, но и внутренние.

Когда вы используете Maven для создания проекта, он разбирается во всем. Поэтому, если от log4j зависит много модулей (возможно, все), то он будет включен только один раз. Есть некоторые проблемы, если ваши модули зависят от разных версий log4j, но этот подход обычно работает нормально.

Также полезно (если более 1-2 разработчиков работают вместе) создать внутренний репозиторий (например, Artifactory) и использовать его для внутренних целей. Это значительно упрощает работу с библиотеками, которых нет в общедоступных репозиториях (просто добавьте их в свое внутреннее репо!), И вы также можете использовать инструменты сборки, чтобы отправлять туда сборки своего собственного кода, чтобы другие могли использовать модули, не проверяя код (полезно в более крупных проектах)

person Kris    schedule 28.05.2009

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

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

Например, если у вас есть 4 проекта, parent, core, ui и utils, вы можете объявить все внешние зависимости и внутренние версии проекта в родительском. Затем дочерние проекты наследуют эту конфигурацию для любых объявляемых ими зависимостей. Если все модули должны иметь одну и ту же версию, их можно даже объявить как свойства в родительском элементе.

Примерный родитель выглядит следующим образом:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>name.seller.rich</groupId>
  <artifactId>parent</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>1.4</version>
      </dependency>
      <dependency>
        <groupId>name.seller.rich</groupId>
        <artifactId>ui</artifactId>
      <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>name.seller.rich</groupId>
        <artifactId>core</artifactId>
        <version>${project.version}</version>
      </dependency>
      <dependency>
        <groupId>name.seller.rich</groupId>
        <artifactId>utils</artifactId>
        <version>${project.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <modules>
    <module>utils</module>
    <module>core</module>
    <module>ui</module>
  </modules>
</project>

А проекты utils, core и ui наследуют все соответствующие версии. утилиты:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>name.seller.rich</groupId>
  <artifactId>utils</artifactId>
  <!--note version not declared as it is inherited-->
  <parent>
    <artifactId>parent</artifactId>
    <groupId>name.seller.rich</groupId>
    <version>1.0.0</version>
  </parent>
  <dependencies>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
    </dependency>
  </dependencies>
</project>

основной:

<project>
<modelVersion>4.0.0</modelVersion>
<groupId>name.seller.rich</groupId>
<artifactId>core</artifactId>
<parent>
  <artifactId>parent</artifactId>
  <groupId>name.seller.rich</groupId>
  <version>1.0.0</version>
</parent>
<dependencies>
  <dependency>
    <groupId>name.seller.rich</groupId>
    <artifactId>utils</artifactId>
  </dependency>
</dependencies>

ui:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>name.seller.rich</groupId>
  <artifactId>ui</artifactId>
  <parent>
    <artifactId>parent</artifactId>
    <groupId>name.seller.rich</groupId>
    <version>1.0.0</version>
  </parent>
  <dependencies>
    <dependency>
      <groupId>name.seller.rich</groupId>
      <artifactId>core</artifactId>
    </dependency>
  </dependencies>
</project>
person Rich Seller    schedule 30.07.2009
comment
Есть ли что-то подобное для плагинов? Например, если я хочу установить для версии maven-compiler-plugin значение 3.1 во всех проектах, могу ли я сделать это в родительском POM? А как насчет конфигурации компилятора? - person Garret Wilson; 13.12.2014
comment
Ах, неважно - я нашел элемент pluginManagement; он не был указан в основном списке разделов на maven.apache.org/pom.html И мне пришлось смотреть дальше вниз. - person Garret Wilson; 13.12.2014

Я составил список лучших практик. Вот самые важные.

  • Always use the maven-enforcer-plugin
    • Enforce dependency convergence
      • Otherwise it's possible that you depend on two different jars which both depend on log4j. Which one gets used at compile time depends on a set of rules that you shouldn't have to remember. They can both (!) get exported as transitive dependencies.
    • Require plugin versions (for all plugins, even the built in ones)
      • Define them in pluginManagement in the parent pom to define versions
      • В противном случае новая версия maven-surefire-plugin может сломать вашу сборку
  • Используйте dependencyManagement в родительском pom для единообразного использования версий во всех модулях
  • Periodically run mvn dependency:analyze
    • It's possible that you're getting a dependency transitively that you directly depend on at compile time. If so, it's important to add it to your pom with the version you require. This plays nicely with the enforcer plugin.
    • Возможно, вы объявляете дополнительные зависимости, которые не используете. Это не работает должным образом в 100% случаев, особенно с библиотеками, в которых предусмотрены дополнительные компоненты (т.е. slf4j-api определяется правильно, а slf4j-log4j12 не работает).
person Craig P. Motlin    schedule 20.08.2011

Следующий вопрос о. Если я объявлю Log4J в разделе родительского объекта, а подпроект не будет его использовать, будет ли он включен в любом случае?

Нет. Управление зависимостями устанавливает только версию по умолчанию и, возможно, область действия (я видел, что оба варианта кажутся унаследованными и не наследуются, поэтому вам нужно будет найти его самостоятельно). Чтобы включить зависимость в дочерний модуль, вам необходимо объявить ее как зависимость модуля и опустить элемент версии. Вы можете переопределить значение по умолчанию в дочернем модуле, просто включив номер версии в элемент зависимости POM дочернего модуля.

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

В этом случае и да, и нет.

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

Для модулей, которые не связаны напрямую, но создаются одной командой внутри компании, вы можете рассмотреть возможность объявления версий по умолчанию для общих библиотек, таких как утилиты тестирования, утилиты ведения журнала и т. Д., Чтобы команда могла работать со стандартными версиями инструменты, которые вы определили как часть своих лучших практик. Помните, что вы всегда можете увеличить версию своей супер-POM, если стандартизируете новый набор общих библиотек. Где вы проводите границу между стандартизованной библиотекой и инструментами и конкретными библиотеками и инструментами для проекта, зависит от вас, но вашей команде должно быть легко найти это.

person DavidValeri    schedule 28.05.2009

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

Мы пробуем модель, в которой мы отделяем dependencyManagement от нашего общего родителя, а затем импортируем наш корпоративный pom dependencyManagement в pom проекта верхнего уровня. Это позволяет нам выборочно определять параметры проекта по умолчанию, которые отменяют корпоративные параметры по умолчанию.

Вот исходный сценарий:

A   defines version 1.0 of foo.jar as the corporate default
B   child of A
C1, C2, C3  children of B
D1, D2, D3 children of C1, C2, C3 respectively

Если для D1 и D2 требуется foo.jar версии 1.1, то мы выбрали следующий вариант:

  1. Объявите foo.jar версии 1.1 как зависимость в B, чтобы казалось, что C1, C2, C3 и D3 также зависят от версии 1.1
  2. Объявите foo.jar версии 1.1 как зависимость в D1 и D2, переместив объявление зависимости в несколько мест глубже в иерархии нашего проекта.

Вот что мы пробуем:

A   defines version 1.0 of foo.jar as the corporate default
B   dependencyManagement: imports A, declares a default of foo.jar version 1.1
C1, C2, C3  children of B
D1, D2, D3 children of C1, C2, C3 respectively

Теперь D1 и D2 просто объявляют зависимость от foo.jar и берут версию 1.1 из блока dependencyManagement B.

person Dwight Shih    schedule 12.05.2011

В многомодульном проекте я помещаю все общие зависимости в элемент родительского pom.xml. Я не уверен, что это было бы наилучшей практикой, если бы модули не были связаны с одним и тем же проектом.

person MikeJ    schedule 28.05.2009