«1. Обзор

В этом кратком руководстве мы рассмотрим, как Maven, инструмент, основанный на концепции объектной модели проекта (POM), может использовать спецификацию или «ведомость материалов».

Для получения более подробной информации о Maven вы можете прочитать нашу статью Учебник по Apache Maven.

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.

Ниже приведен пример того, как написать файл спецификации:

<project ...>
	
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Baeldung-BOM</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>BaelDung-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 способа использовать предыдущий BOM-файл в нашем проекте, и тогда мы будем готовы объявить наши зависимости, не беспокоясь о номерах версий.

Мы можем наследовать от родителя:

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Test</name>
    <parent>
        <groupId>baeldung</groupId>
        <artifactId>Baeldung-BOM</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
</project>

Как мы видим, наш проект Test наследует Baeldung-BOM.

Мы также можем импортировать спецификацию.

В больших проектах подход наследования неэффективен, поскольку проект может наследовать только одного родителя. Альтернативой является импорт, поскольку мы можем импортировать столько спецификаций, сколько нам нужно.

Давайте посмотрим, как мы можем импортировать BOM-файл в наш проект POM:

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>baeldung</groupId>
    <artifactId>Test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>Test</name>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>baeldung</groupId>
                <artifactId>Baeldung-BOM</artifactId>
                <version>0.0.1-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

2.6. Перезапись зависимости BOM

Порядок приоритета версии артефакта:

  1. The version of the artifact’s direct declaration in our project pom
  2. The version of the artifact in the parent project
  3. The version in the imported pom, taking into consideration the order of importing files
  4. dependency mediation
    Мы можем перезаписать версию артефакта, явно определив артефакт в pom нашего проекта с желаемой версией Если один и тот же артефакт определен с разными версиями в 2 импортированных BOM, то версия в BOM-файле, которая была объявлена ​​первой, выиграет

3. Спецификация Spring

Мы можем обнаружить, что сторонняя библиотека или другой проект 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.