Управление зависимостями Maven

Одной из ключевых возможностей Maven является управление зависимостями. Когда мы имеем дело с многомодульными проектами (содержащими сотни или тысячи модулей или подпроектов), зависимости между модулями становятся очень сложными, а управление — очень трудным. В такой ситуации Maven предлагает подход с высоким уровнем контроля.


Обнаружение транзитивных зависимостей

Довольно распространённая ситуация: например, A зависит от другой библиотеки B. Если другой проект C хочет использовать A, то проекту C также нужно использовать библиотеку B.

Maven позволяет избежать необходимости искать все требуемые библиотеки. Maven читает файлы проекта (pom.xml), чтобы найти зависимости между проектами.

Всё, что нам нужно сделать, — определить прямые зависимости в pom каждого проекта. Maven сделает всё остальное за нас.

При транзитивных зависимостях граф всех включённых библиотек может быстро расти. Когда есть дублирующиеся библиотеки, количество возможных ситуаций продолжает увеличиваться. Maven предоставляет некоторые возможности для контроля степени транзитивных зависимостей.

Характеристика Описание функции
Посредничество зависимостей Определяет, какая версия зависимости будет использоваться, когда одновременно появляются несколько созданных вручную версий. Если две версии зависимости находятся на одной глубине в дереве зависимостей, будет использована первая объявленная зависимость.
Управление зависимостями Вы можете напрямую указать, какую созданную вручную версию использовать. Например, предположим, что проект C включает проект B в качестве своей зависимости, а проект B зависит от проекта A. В этом случае вы можете явно указать версию проекта A, которая должна использоваться, когда на проект B ссылаются. Это означает, что вы можете управлять тем, какая конкретная версия проекта A будет использоваться проектом B.
Область действия зависимости Зависимости, включённые в каждую фазу процесса сборки.
Исключение зависимостей Любую транзитивную зависимость можно исключить с помощью элемента "exclusion". Например, A зависит от B, B зависит от C, поэтому A может пометить C как "excluded".
Необязательная зависимость Любую транзитивную зависимость можно пометить как необязательную с помощью элемента "optional". Например: A зависит от B, а B зависит от C. Следовательно, B может пометить C как необязательную, чтобы A больше не использовал C.

Область действия зависимости

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

Область действия Описание
Compile Эта область действия указывает, что связанная зависимость действительна только в classpath проекта. Значение по умолчанию.
Provided Эта область видимости указывает на то, что соответствующая зависимость предоставляется JDK времени выполнения или веб-сервером.
Время выполнения Эта область видимости указывает на то, что соответствующая зависимость не требуется на этапе компиляции, но требуется на этапе выполнения.
Тест Эта область видимости указывает на то, что соответствующая зависимость предназначена только для этапов компиляции и выполнения тестов.
Система Эта область видимости указывает на то, что необходимо указать системный путь.
Импорт Эта область видимости используется только когда зависимость определена в pom. В то же время, POM-файл текущего проектазависимости, определённые в разделе <dependencyManagement>, могут заменить конкретный POM.

Управление зависимостями

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

Ниже приведено подробное объяснение графа зависимостей выше:

  • App-UI-WAR зависит от App-Core-lib и App-Data-lib.

  • Root является родительским проектом для App-Core-lib и App-Data-lib.

  • Root определяет Lib1, lib2 и Lib3 как зависимости в своём разделе dependencies.

Код файла pom.xml для App-UI-WAR выглядит следующим образом:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-UI-WAR</artifactId> <version>1.0</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>com.companyname.groupname</groupId> <artifactId>App-Core-lib</artifactId> <version>1.0</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname</groupId> <artifactId>App-Data-lib</artifactId> <version>1.0</version> </зависимость> </зависимости> </проект>

Код файла pom.xml для App-Core-lib выглядит следующим образом:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Core-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project>

Код файла pom.xml для App-Data-lib выглядит следующим образом:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>Root</artifactId> <groupId>com.companyname.groupname</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>App-Data-lib</artifactId> <version>1.0</version> <packaging>jar</packaging> </project>

Код файла pom.xml для Root выглядит следующим образом:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.companyname.groupname</groupId> <artifactId>Root</artifactId> <version>1.0</version> <packaging>pom</packaging> <dependencies> <dependency> <groupId>com.companyname.groupname1</groupId> <artifactId>Lib1</artifactId> <version>1.0</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname2</groupId> <artifactId>Lib2</artifactId> <version>2.1</version> </dependency> </dependencies> <dependencies> <dependency> <groupId>com.companyname.groupname3</groupId> <artifactId>Lib3</artifactId> <version>1.1</version> </dependency> </dependencies> </project>

Теперь, когда мы собираем проект App-UI-WAR, Maven найдёт все зависимости, обходя граф зависимостей, и соберёт приложение.

На приведённом выше примере мы можем изучить следующие ключевые концепции:

  • Общие зависимости можно объединить вместе с помощью концепции parent pom. Зависимости проектов App-Data-lib и App-Core-lib перечислены в проекте Root (обратите внимание на тип упаковки Root — это POM).
  • Нет необходимости объявлять Lib1, lib2, Lib3 как зависимости в App-UI-W. Maven реализует эту деталь с помощью механизма транзитивных зависимостей.
Другие расширения