Как указать на каком этапе сборки приложения библиотека должна использоваться в Maven
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Maven Scopes: указание этапа использования библиотеки
Краткий ответ
В Maven область видимости (scope) зависимости указывается в теге <scope> элемента <dependency>. Это определяет, когда и как библиотека будет использоваться: при компиляции, тестировании или в runtime.
Maven Scopes
1. compile (по умолчанию)
Используется на всех этапах сборки и включается в финальный артефакт.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</version>
<!-- <scope>compile</scope> (опционально, это значение по умолчанию) -->
</dependency>
Когда использовать:
- Основные библиотеки вашего приложения
- Фреймворки (Spring, Hibernate и т.д.)
- Утилиты, которые нужны в production
Доступна в:
- Compile classpath (компиляция кода)
- Test classpath (компиляция и запуск тестов)
- Runtime classpath (запуск приложения)
2. test
Используется только при компиляции и запуске тестов, НЕ включается в финальный артефакт.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.6.1</version>
<scope>test</scope>
</dependency>
Когда использовать:
- Фреймворки для тестирования (JUnit, TestNG)
- Библиотеки для mock-объектов (Mockito, PowerMock)
- Библиотеки для assertions (AssertJ, Hamcrest)
- Тестовые утилиты
Доступна в:
- Test classpath только
- НЕ доступна при компиляции основного кода
3. provided
Компилируется с проектом, но не включается в финальный артефакт (предполагается, что будет предоставлена окружением).
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
Когда использовать:
- Сервлет API (при разработке веб-приложения для Tomcat)
- Компилятор-зависимые библиотеки (Lombok, @Nullable аннотации)
- Библиотеки, предоставляемые контейнером (J2EE)
Почему:
- Сервер приложений (Tomcat, JBoss) уже содержит эти библиотеки
- Не нужно включать дубликаты в WAR/JAR файл
Доступна в:
- Compile classpath (для компиляции)
- Test classpath (для тестов)
- НЕ доступна в runtime (окружение предоставит)
4. runtime
НЕ используется при компиляции, но включается в финальный артефакт и доступна при запуске.
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.1.214</version>
<scope>runtime</scope>
</dependency>
Когда использовать:
- JDBC драйверы (MySQL, PostgreSQL, Oracle)
- Реализации интерфейсов (логирование, конфигурация)
- Динамически загружаемые библиотеки
Почему:
- Код использует интерфейсы (например, java.sql.Connection)
- Конкретная реализация выбирается при runtime
Доступна в:
- Test classpath (для запуска тестов)
- Runtime classpath (при запуске приложения)
- НЕ доступна при компиляции основного кода
5. import (BOM - Bill of Materials)
Используется только в рамках <dependencyManagement> для импорта POM-файла.
<dependencyManagement>
<dependencies>
<!-- Import зависимостей из Spring Boot BOM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Теперь можно использовать версии из BOM без указания version -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- version наследуется из BOM -->
</dependency>
</dependencies>
Когда использовать:
- Управление версиями для множества зависимостей
- Использование BOM от фреймворков (Spring Boot, Quarkus)
6. system (deprecated)
Ссылается на JAR файл в файловой системе (устарело, не рекомендуется).
<dependency>
<groupId>custom.lib</groupId>
<artifactId>custom-lib</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/tools.jar</systemPath>
</dependency>
Сравнительная таблица Scopes
| Scope | Компиляция | Тесты | Runtime | В артефакте |
|---|---|---|---|---|
| compile | Да | Да | Да | Да |
| test | Нет | Да | Нет | Нет |
| provided | Да | Да | Нет | Нет |
| runtime | Нет | Да | Да | Да |
| import | - | - | - | - |
| system | Да | Да | Да | Да |
Практические примеры
Полный пример pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>myapp</artifactId>
<version>1.0.0</version>
<dependencyManagement>
<dependencies>
<!-- Import BOM для версионирования -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Compile scope: основной фреймворк -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Compile scope: ORM -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Provided scope: servlet API предоставляется Tomcat -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Provided scope: Lombok для аннотаций -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- Runtime scope: JDBC драйвер -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Test scope: JUnit -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Test scope: Mockito -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<!-- Test scope: AssertJ -->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<!-- Test scope: тестовая БД -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Опциональные зависимости
Можно отметить зависимость как опциональную, означая, что она может быть нужна, но не требуется:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<optional>true</optional>
</dependency>
Потребитель вашей библиотеки должен явно добавить эту зависимость, если она ему нужна.
Исключение нежелательных зависимостей
Если зависимость транзитивно подтягивает ненужные библиотеки:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</exclusion>
</exclusions>
</dependency>
Команды для анализа зависимостей
# Показать дерево зависимостей
mvn dependency:tree
# Показать только конфликты версий
mvn dependency:tree -Dverbose
# Анализ неиспользуемых зависимостей
mvn dependency:analyze
Вывод
Maven scopes позволяют точно контролировать, когда и где используются зависимости:
- compile — по умолчанию, для основного кода
- test — только для тестов
- provided — компилируется, но не включается (окружение предоставит)
- runtime — НЕ для компиляции, но в runtime
- import — для импорта BOM файлов
Правильное использование scopes снижает размер артефактов и предотвращает конфликты зависимостей.