← Назад к вопросам

Как указать на каком этапе сборки приложения библиотека должна использоваться в Maven

2.0 Middle🔥 121 комментариев
#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# 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 снижает размер артефактов и предотвращает конфликты зависимостей.

Как указать на каком этапе сборки приложения библиотека должна использоваться в Maven | PrepBro