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

Ответ

Scope в Maven определяет жизненный цикл зависимости и её видимость (включается ли она в classpath) для различных этапов сборки, тестирования и выполнения проекта.

Основные значения scope:

Scope Описание Включается в classpath для... Пример использования
compile (По умолчанию) Зависимость доступна на всех этапах. Компиляции, тестов, выполнения. spring-core, lombok.
provided Зависимость предоставляется средой выполнения (JDK, контейнер сервлетов). Компиляции и тестов, но не для сборки исполняемого артефакта (WAR/JAR). servlet-api, javax.annotation-api.
runtime Зависимость не нужна для компиляции, но требуется во время выполнения. Тестов и выполнения, но не для компиляции. JDBC-драйвер базы данных (например, mysql-connector-java).
test Зависимость нужна только для фазы тестирования. Только для компиляции и запуска тестов (src/test/java). junit, mockito.
system Аналогичен provided, но требует явного указания пути к JAR-файлу в системе. Компиляции и тестов. Используется редко, так как делает сборку непереносимой. Внутренние, неопубликованные библиотеки.
import Используется только в секции <dependencyManagement> для импорта зависимостей из другого POM (обычно BOM). Не определяет classpath. Управляет версиями. Импорт Spring Boot BOM: spring-boot-dependencies.

Пример объявления в pom.xml:

<dependencies>
    <!-- Зависимость только для тестов -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>

    <!-- Зависимость, предоставляемая контейнером (Tomcat) -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

Практическое влияние: Scope влияет на содержимое итоговых артефактов (JAR/WAR). Например, зависимости с provided и test не будут включены в WEB-INF/lib WAR-файла.

Ответ 18+ 🔞

А, ну ты про scope в Maven спрашиваешь? О, это, блядь, классика! Сидит такой новичок, накидывает в pom.xml зависимости, а потом у него артефакт размером с дирижабль, потому что он, сука, junit на продакшен затащил. Пиздец, а не сборка.

Смотри сюда, я тебе на пальцах, но с технической точностью, объясню, что это за зверь такой — scope. Это, грубо говоря, указание Maven'у, когда и куда воткнуть твою библиотеку. Чтобы не тащить в продакшен то, что нужно только для тестов, понимаешь? Экономия места и нервов.

Основные значения, которые тебе надо знать, чтобы не выглядеть мудаком:

Scope Суть вопроса Когда в classpath? Где применяется?
compile (Дефолтный, если не указал) Всё включено, брат. Везде: компиляция, тесты, запуск. Ну, spring-core, lombok — без них проект — говно.
provided «Не трогай, у меня своя есть!» Среда выполнения (Tomcat, JDK) уже принесёт. На компиляции и в тестах. В финальный JAR/WAR — НЕ лезет. servlet-api. Ты же не будешь таскать его в WAR, когда Tomcat свой подсунет?
runtime «На компиляции не нужен, но чтобы работало — воткни». В тестах и при запуске. На компиляции — не видно. JDBC-драйвер (mysql-connector). Интерфейсы ты скомпилировал с javax.sql, а вот саму железяку для подключения дай на runtime.
test «Только для извращений в src/test». Только для компиляции и запуска тестов. В продакшен — ни-ни. junit, mockito. Представь, если бы @Test летел на боевой сервер — ёперный театр!
system «Вот тут лежит, ищи сам». Хуйня полная, непереносимая. Компиляция, тесты. Какая-нибудь левая company-secret-superlib.jar с жёстким путём. Используй, только если совсем еблан.
import «Я не библиотека, я — начальник!» Только в <dependencyManagement>. Никуда не включается. Управляет версиями из BOM. Импорт spring-boot-dependencies, чтобы версии не конфликтовали.

Вот, смотри, как в деле выглядит, код не трогаю, он святой:

<dependencies>
    <!-- Это только для тестов, нахуй! -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.9.2</version>
        <scope>test</scope>
    </dependency>

    <!-- Это Tomcat сам даст, не суй в WAR, оболтус! -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

А на практике: если scope проёбан, получишь либо толстенный артефакт, либо ClassNotFoundException на боевом. Всё просто: test и provided в итоговую сборку не попадают. Остальные — пожалуйста. Главное — думай, блядь, головой, что куда ты пихаешь.