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

Что такое Scope зависимости?

2.0 Middle🔥 141 комментариев
#SOLID и паттерны проектирования#Spring Framework

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

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

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

Scope зависимостей в Maven и Gradle

Scope (область видимости) зависимости определяет, на каких этапах сборки проекта и на какие другие проекты распространяется эта зависимость. Это один из ключевых механизмов управления зависимостями в Java проектах.

Основные Scopes в Maven

1. compile (по умолчанию)

<!-- Зависимость доступна на всех classpath и компилируется в JAR/WAR -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
    <scope>compile</scope>  <!-- или опустить, так как это значение по умолчанию -->
</dependency>

Когда используется:

  • Нужна в основном коде приложения
  • Нужна в production среде
  • Компилируется в финальный артефакт (JAR/WAR)

Примеры:

  • Spring Framework
  • Lombok
  • Jackson
  • Apache Commons

2. test

<!-- Зависимость используется только для тестов -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

Когда используется:

  • Используется только в тестовом коде (src/test/java)
  • НЕ компилируется в финальный артефакт
  • Доступна только при запуске тестов

Примеры:

  • JUnit
  • Mockito
  • Testcontainers
  • AssertJ

Структура проекта:

src/
├── main/java/      (test зависимости НЕ видны здесь)
└── test/java/      (test зависимости видны здесь)

3. provided

<!-- Зависимость предоставляется runtime окружением -->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

Когда используется:

  • Используется в коде, но предоставляется контейнером (Tomcat, JBoss и т.д.)
  • НЕ компилируется в WAR файл
  • Нужна при компиляции, но не нужна в production

Примеры:

  • javax.servlet-api (Tomcat содержит свою реализацию)
  • Java EE APIs
  • Application server specific libs

Разница между compile и provided:

// Код использует Servlet API
public class MyServlet extends HttpServlet {
    // HttpServlet из javax.servlet
}

// Если scope=compile: HttpServlet включается в WAR
// Если scope=provided: HttpServlet НЕ включается в WAR
//    (Tomcat предоставит свою версию при runtime)

4. runtime

<!-- Зависимость нужна только при выполнении, не нужна при компиляции -->
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.5.1</version>
    <scope>runtime</scope>
</dependency>

Когда используется:

  • НЕ нужна при компиляции
  • Нужна при запуске приложения
  • Не должна быть указана в import statements

Примеры:

  • JDBC драйверы (PostgreSQL, MySQL, MongoDB)
  • Runtime логирование имплементации (SLF4J)
  • Конфигурационные файлы
// Вы пишете код используя интерфейсы
DriverManager.getConnection("jdbc:postgresql://localhost/db");

// PostgreSQL драйвер (postgresql dependency) нужен только при runtime
// чтобы DriverManager знал как подключиться

// Если scope=compile: PostgreSQL jar включится в приложение
// Если scope=runtime: PostgreSQL jar НЕ включится в приложение
//    но должен быть в classpath при запуске

5. system

<!-- Зависимость на локальном файловой системе -->
<dependency>
    <groupId>com.local</groupId>
    <artifactId>my-local-lib</artifactId>
    <version>1.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/lib/my-local-lib.jar</systemPath>
</dependency>

Когда используется:

  • Локальная JAR которая не в репозитории
  • Редко используется в современных проектах
  • Проблемы с портативностью

6. import (только для POM файлов)

<!-- Используется для наследования зависимостей из другого POM -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>2021.0.5</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

Таблица всех Scopes

ScopeCompileTestRuntimeПримеры
compileSpring, Guava
testJUnit, Mockito
providedservlet-api
runtimeJDBC драйверы
systemЛокальные JAR
import(POM только)Bill of Materials

Практические примеры pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0</version>
    
    <dependencies>
        <!-- COMPILE: основная бизнес-логика -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>3.0.0</version>
            <!-- scope=compile (по умолчанию) -->
        </dependency>
        
        <!-- COMPILE: утилиты -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.12.0</version>
        </dependency>
        
        <!-- PROVIDED: сервлет API (предоставляется Tomcat) -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>
        
        <!-- RUNTIME: JDBC драйвер -->
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.5.1</version>
            <scope>runtime</scope>
        </dependency>
        
        <!-- TEST: фреймворк для тестирования -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        
        <!-- TEST: моки -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>5.0.0</version>
            <scope>test</scope>
        </dependency>
        
        <!-- TEST: Spring для тестов -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <version>3.0.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Scopes в Gradle

dependencies {
    // COMPILE (по умолчанию)
    implementation 'org.springframework.boot:spring-boot-starter-web:3.0.0'
    
    // TEST
    testImplementation 'junit:junit:4.13.2'
    testImplementation 'org.mockito:mockito-core:5.0.0'
    
    // PROVIDED (обычно используется compileOnly)
    compileOnly 'javax.servlet:javax.servlet-api:4.0.1'
    
    // RUNTIME
    runtimeOnly 'org.postgresql:postgresql:42.5.1'
    
    // Для классов используемых в тестах из основного кода
    testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.0'
}

Реальные ошибки Scope

Ошибка 1: compile вместо test

<!-- ПЛОХО -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <!-- Без scope (по умолчанию compile) -->
</dependency>

Проблема: JUnit включится в production JAR (ненужный вес)

<!-- ХОРОШО -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>  <!-- Только для тестов -->
</dependency>

Ошибка 2: provided вместо compile

<!-- ПЛОХО -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
    <scope>provided</scope>  <!-- Где будет предоставлена? -->
</dependency>

Проблема: Guava не предоставляется контейнером, приложение упадёт

<!-- ХОРОШО -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.1-jre</version>
    <!-- scope=compile (по умолчанию) -->
</dependency>

Как выбрать правильный Scope?

// Спроси себя:

// 1. Нужна ли эта зависимость в production?
//    ДА  → compile (или runtime если не нужна при компиляции)
//    НЕТ → test или provided

// 2. Это сервис или API, предоставляемые контейнером?
//    ДА  → provided
//    НЕТ → compile

// 3. Это только для тестов?
//    ДА  → test
//    НЕТ → compile, runtime или provided

// 4. Нужна только при запуске, не при компиляции?
//    ДА  → runtime
//    НЕТ → compile

Проверка зависимостей

# Вывести дерево зависимостей
mvn dependency:tree

# Вывести с указанием scope
mvn dependency:tree -DoutputFile=dependencies.txt

# Найти зависимости с конфликтами версий
mvn enforcer:enforce

# Анализ неиспользуемых зависимостей
mvn dependency:analyze

Bill of Materials (BOM)

<!-- Централизованное управление версиями через import scope -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2021.0.5</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<!-- Теперь все Spring Cloud зависимости унифицированы -->
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
        <!-- version не нужна, возьмётся из BOM -->
    </dependency>
</dependencies>

Итого

  • compile (default) — основной код, включается в JAR
  • test — только для тестов, НЕ включается в JAR
  • provided — предоставляется контейнером, НЕ включается в JAR
  • runtime — не нужна при компиляции, только при запуске
  • system — редко используется, локальная JAR
  • import — для BOM файлов

Правильное использование Scopes снижает размер артефактов и избегает конфликтов зависимостей.

Что такое Scope зависимости? | PrepBro