1. Обзор
В этом кратком руководстве мы рассмотрим, как Maven, инструмент, основанный на концепции объектной модели проекта (POM), может использовать спецификацию или «ведомость материалов».
Подробнее о Maven можно узнать в нашей статье Apache Maven Tutorial .
2. Концепции управления зависимостями
Чтобы понять, что такое спецификация и для чего мы можем ее использовать, нам сначала нужно изучить основные понятия.
2.1. Что такое Maven POM?
Maven POM — это XML-файл, содержащий информацию и конфигурации (о проекте), которые используются Maven для импорта зависимостей и сборки проекта.
2.2. Что такое Maven BOM?
BOM расшифровывается как Bill Of Materials. BOM — это особый вид POM, который используется для управления версиями зависимостей проекта и обеспечивает центральное место для определения и обновления этих версий.
Спецификация обеспечивает гибкость добавления зависимости к нашему модулю, не беспокоясь о версии, от которой мы должны зависеть.
2.3. Транзитивные зависимости
Maven может обнаружить библиотеки, необходимые для наших собственных зависимостей, в нашем файле pom.xml
и включить их автоматически. Количество уровней зависимости, из которых собираются библиотеки, не ограничено.
Конфликт здесь возникает, когда две зависимости относятся к разным версиям определенного артефакта. Какой из них будет включен Maven?
Ответ здесь — «ближайшее определение». Это означает, что используемая версия будет ближайшей к нашему проекту в дереве зависимостей. Это называется посредничеством зависимостей.
Давайте посмотрим на следующий пример, чтобы прояснить посредничество зависимостей:
A -> B -> C -> D 1.4 and A -> E -> D 1.0
Этот пример показывает, что проект A
зависит от B
и E.
B
и E
имеют свои собственные зависимости, которые сталкиваются с разными версиями артефакта D.
Артефакт D
1.0 будет использоваться в сборке проекта A
, потому что путь через E
короче.
Существуют различные методы определения того, какую версию артефактов следует включить:
- Мы всегда можем гарантировать версию, объявив ее явно в POM нашего проекта. Например, чтобы гарантировать использование
D
1.4, мы должны явно добавить его как зависимость в файлpom.xml
. - Мы можем использовать раздел «
Управление зависимостями
» для управления версиями артефакта, как мы объясним позже в этой статье.
2.4. Управление зависимостями
Проще говоря, управление зависимостями — это механизм для централизации информации о зависимостях.
Когда у нас есть набор проектов, которые наследуют общего родителя, мы можем поместить всю информацию о зависимостях в общий файл POM, называемый BOM.
Ниже приведен пример того, как написать файл BOM:
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>foreach</groupId>
<artifactId>ForEach-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>ForEach-BOM</name>
<description>parent pom</description>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Как мы видим, спецификация — это обычный файл POM с разделом dependencyManagement
, куда мы можем включить всю информацию и версии артефакта.
2.5. Использование BOM-файла
Есть 2 способа использовать предыдущий файл спецификации в нашем проекте, и тогда мы будем готовы объявить наши зависимости, не беспокоясь о номерах версий.
Мы можем наследовать от родителя:
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>foreach</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Test</name>
<parent>
<groupId>foreach</groupId>
<artifactId>ForEach-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
</project>
Как мы видим, наш проект Test наследует ForEach-BOM.
Мы также можем импортировать спецификацию.
В более крупных проектах подход наследования неэффективен, поскольку проект может наследовать только одного родителя. Альтернативой является импорт, поскольку мы можем импортировать столько спецификаций, сколько нам нужно.
Давайте посмотрим, как мы можем импортировать файл спецификации в наш проект POM:
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>foreach</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Test</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>foreach</groupId>
<artifactId>ForEach-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.6. Перезапись зависимости спецификации
Порядок приоритета версии артефакта:
- Версия прямого объявления артефакта в нашем проекте pom
- Версия артефакта в родительском проекте
- Версия в импортируемом pom с учетом порядка импорта файлов
- посредничество в зависимости
- Мы можем перезаписать версию артефакта, явно указав артефакт в pom нашего проекта с желаемой версией.
- Если один и тот же артефакт определен с разными версиями в 2 импортированных спецификациях, то версия в файле спецификации, которая была объявлена первой, будет иметь преимущество.
3. Весенняя спецификация
Мы можем обнаружить, что сторонняя библиотека или другой проект Spring использует транзитивную зависимость от более старой версии. Если мы забудем явно объявить прямую зависимость, могут возникнуть непредвиденные проблемы.
Чтобы преодолеть такие проблемы, Maven поддерживает концепцию зависимости BOM.
Мы можем импортировать spring-framework-bom
в наш раздел dependencyManagement
, чтобы убедиться, что все зависимости Spring имеют одну и ту же версию:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>4.3.8.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Нам не нужно указывать атрибут версии
, когда мы используем артефакты Spring, как в следующем примере:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependencies>
4. Вывод
В этой быстрой статье мы показали концепцию Maven Bill-Of-Material и то, как централизовать информацию и версии артефакта в общем POM.
Проще говоря, мы можем либо наследовать, либо импортировать его, чтобы использовать преимущества спецификации.
Примеры кода в статье можно найти на GitHub .