2009-05-28 1 views
19

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

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

+0

Fail @Kieveli для бесполезного неосторожного ответа. – Jherico

+0

Я думаю, что общие/общие зависимости обязательно должны быть настроены в разделе dependencyManagement. Вопрос в том, как раз вы идете по этому пути, вы не должны добавлять все зависимости (общие или нет) в dependencyManagement. Я могу видеть про и минусы для обоих. Любые лучшие практики для этого? – Hardy

ответ

8

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

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

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

0

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

1

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

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

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

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

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

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

31

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

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

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

Что-то подобное доступно для плагинов? Например, если я хочу установить версию 'maven-compiler-plugin' на' 3.1' по проектам, могу ли я сделать это в родительском POM? Как насчет конфигурации компилятора? –

+1

Ах, неважно --- Я нашел элемент 'pluginManagement'; он не был указан в главном списке разделов на http://maven.apache.org/pom.html, и мне пришлось смотреть дальше. –

1

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

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

  1. Declare foo.jar версии 1.1 как в 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 В.

16

Я написал список best practices. Вот самые важные.

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