1. Обзор
Maven — один из самых популярных инструментов сборки в экосистеме Java, и одной из его основных функций является управление зависимостями.
В этом руководстве мы собираемся описать и изучить механизм, который помогает управлять транзитивными зависимостями в проектах Maven — области зависимостей.
2. Транзитивная зависимость
В Maven есть два типа зависимостей: прямые и транзитивные.
Прямые зависимости — это те, которые мы явно включаем в проект.
Их можно включить с помощью тегов <dependency> :
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
С другой стороны, транзитивные зависимости требуются прямыми зависимостями. Maven автоматически включает необходимые транзитивные зависимости в наш проект.
Мы можем перечислить все зависимости, включая транзитивные зависимости в проекте, с помощью команды mvn dependency:tree
.
3. Области зависимости
Области действия зависимостей могут помочь ограничить транзитивность зависимостей. Они также изменяют путь к классам для различных задач сборки. Maven имеет шесть областей зависимостей по умолчанию.
И важно понимать, что каждая область действия — кроме импорта
— влияет на транзитивные зависимости.
3.1. Компиляция
Это область по умолчанию, если не указана другая область.
Зависимости с этой областью доступны в пути к классам проекта во всех задачах сборки. Они также распространяются на зависимые проекты.
Что еще более важно, эти зависимости также транзитивны:
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
3.2. При условии
Мы используем эту область, чтобы отметить зависимости, которые должны быть предоставлены во время выполнения JDK или контейнером.
Хорошим вариантом использования для этой области будет веб-приложение, развернутое в каком-либо контейнере, где контейнер уже сам предоставляет некоторые библиотеки. Например, это может быть веб-сервер, который уже предоставляет API сервлетов во время выполнения.
В нашем проекте мы можем определить эти зависимости с предоставленной
областью действия:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
Предоставленные зависимости доступны только во время компиляции и в тестовом пути к классам проекта .
Эти зависимости также не являются транзитивными.
3.3. Время выполнения
Зависимости с этой областью необходимы во время выполнения. Но они нам не нужны для компиляции кода проекта. Из-за этого зависимости, отмеченные областью выполнения
, будут присутствовать в пути к классам среды выполнения и теста, но они будут отсутствовать в пути к классам компиляции.
Драйвер JDBC — хороший пример зависимостей, которые должны использовать область выполнения:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<scope>runtime</scope>
</dependency>
3.4. Тест
Мы используем эту область, чтобы указать, что зависимость не требуется в стандартной среде выполнения приложения, а используется только в целях тестирования.
Тестовые
зависимости не являются транзитивными и присутствуют только для тестовых и исполнительных путей к классам.
Стандартный вариант использования этой области — добавление тестовой библиотеки, такой как JUnit, в наше приложение:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
3.5. Система
Системная
область очень похожа на предоставленную
область. Основное отличие состоит в том, что system
требует, чтобы мы прямо указывали на определенный jar в системе.
Стоит отметить, что область действия системы
устарела .
Важно помнить, что сборка проекта с зависимостями системной
области может завершиться ошибкой на разных машинах, если зависимости отсутствуют или расположены в другом месте, чем указывает один systemPath
:
<dependency>
<groupId>com.foreach</groupId>
<artifactId>custom-dependency</artifactId>
<version>1.3.2</version>
<scope>system</scope>
<systemPath>${project.basedir}/libs/custom-dependency-1.3.2.jar</systemPath>
</dependency>
3.6. импорт
Он доступен только для типа зависимости pom
.
import
указывает, что эта зависимость должна быть заменена всеми действующими зависимостями, объявленными в ее POM.
Здесь ниже зависимость пользовательского проекта
будет заменена всеми зависимостями, объявленными в разделе pom.xml
<dependencyManagement>
пользовательского проекта .
<dependency>
<groupId>com.foreach</groupId>
<artifactId>custom-project</artifactId>
<version>1.3.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
4. Объем и транзитивность
Каждая область зависимости влияет на транзитивные зависимости по-своему. Это означает, что разные транзитивные зависимости могут оказаться в проекте с разными областями.
Однако зависимости с предоставленными
областями и тестом
никогда не будут включены в основной проект.
Давайте подробно рассмотрим, что это означает:
- Для области
компиляции
все зависимости с областьювыполнения
будут подтягиваться с областьювыполнения
в проекте, а все зависимости с областьюкомпиляции
будут подтягиваться с областьюкомпиляции
в проекте. - Для
предоставленной
области зависимости каксреды выполнения
, так и областикомпиляции
будут включены впредоставленную
область в проекте. - Для области
тестирования
транзитивные зависимости каквремени выполнения
, так и областикомпиляции
будут включены в областьтестирования
в проекте. - Для области
выполнения
транзитивные зависимости каксреды выполнения
, так и областикомпиляции
будут подтягиваться вместе с областьювыполнения
в проекте.
5. Вывод
В этой быстрой статье мы сосредоточились на областях зависимостей Maven, их назначении и деталях того, как они работают.
Чтобы углубиться в Maven, лучше всего начать с документации .