Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Например, если у вас есть 4 проекта, родительский, ядро, 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 наследуют все соответствующие версии. Utils:

<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>

щ:

<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>

Ответ 3

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

  • Всегда используйте maven-enforcer-plugin
    • Enforce конвергенция зависимостей
      • В противном случае вы можете зависеть от двух разных банок, которые зависят от log4j. Какой из них используется во время компиляции, зависит от набора правил, которые вам не нужно помнить. Они могут (!) Экспортироваться как транзитивные зависимости.
    • Требовать версии плагина (для всех плагинов, даже встроенных)
      • Определите их в pluginManagement в родительском pom для определения версий
      • В противном случае новая версия maven-surefire-plugin может сломать вашу сборку
  • Используйте функцию dependencyManagement в родительском pom, чтобы последовательно использовать версии во всех модулях.
  • Периодически запускайте зависимость mvn: проанализируйте
    • Возможно, что вы получаете транзитивную зависимость, от которой вы напрямую зависите во время компиляции. Если это так, важно добавить его в свой pom с нужной вам версией. Это прекрасно работает с плагином-исполнителем.
    • Возможно, вы объявляете дополнительные зависимости, которые вы не используете. Это не работает должным образом в 100% случаев, особенно в библиотеках, которые предназначены для создания необязательных фрагментов (т.е. Slf4j-api обнаруживается должным образом, но slf4j-log4j12 не работает).

Ответ 4

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

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

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

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

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

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

Ответ 5

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

Мы тестируем модель, в которой мы разделяем функцию 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 требуется версия 1.1 foo.jar, тогда наш выбор был:

  • Объявите версию foo.jar версии 1.1 как зависимость в B, заставив ее показать, что C1, C2, C3 и D3 также зависят от версии 1.1
  • Объявить 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.

Ответ 6

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