Maven zakresy zależności (scope)

Dodając zależność (dependency) do projektu zarządzanego przez Mavena należy zdecydować pomiędzy jednym z zakresów (scope). Dostępne zakresy to: compile, provided, runtime, test, system, import.

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
    <scope>...</scope>
</dependency>

compile (domyślny)

compile jest domyślnym zakresem – używanym gdy żaden nie jest zdefiniowany:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

Możliwe jest też jawne użycie:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
    <scope>compile</scope>
</dependency>

Zastosowanie tego zakresu zapewnia, że podczas budowania ta zależność pojawi się na classpath przy kompilacji oraz przy uruchamianiu testów. Dodatkowo, jeśli budujemy paczkę (jar,war,zip…) ta zależność także się w niej pojawi. Warto dodać, że wszystkie zależności tego zakresu są propagowane w dół do zależnych modułów/projektów.

provided

Jest to prawie, że identyczny zakres jak compile – zależność pojawi się na classpath przy kompilacji oraz przy uruchamianiu testów. Ale w tym wypadku w wynikowej paczce nie dostaniemy tej zależności (stąd nazwa provided):

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
    <scope>provided</scope>
</dependency>

Warto także dodać, że taka zależność nie jest tranzytywna – nie będzie propagowana do zależnych modułów/projektów.

runtime

Zakres runtime powoduje ograniczenie zależności do dwóch zakresów:
1. czasu działania aplikacji (stąd runtime), gdzie zostaje dostarczony podczas budowania paczki
2. classpath dla testów

Co ciekawe taka zależność nie pojawi się na classpathie dla głównej części (najczęściej jest to src/main/java) naszego projektu – nie będzie można wykorzystać klas tej zależności. Przykładem wykorzystania może być wymuszenie dodania zależności do paczki (w sytuacji gdy takową tworzymy) ale zastrzeżenie użycia klas danej zależności w module.

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
    <scope>runtime</scope>
</dependency>

Zależności z zakresu runtime są tranzytywne.

test

Jak sama nazwa mówi, ten zakres jest przeznaczony do zależności wykorzystywanych tylko w testach (takich jak Mockito czy JUnit):

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

Zależność o zakresie test nie jest tranzytywna – nie będzie propagowana do zależnych modułów/projektów.

system

Pozwala na wskazanie ścieżki do pliku JAR, co powoduje, że zależność nie jest pobierana z repozytorium tylko zaciągana z systemu plików:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/libs/junit_patched.jar</systemPath>
</dependency>

Zależność o zakresie system nie jest tranzytywna – nie będzie propagowana do zależnych modułów/projektów.

import

Jest to zakres wykorzystywany tylko i wyłącznie wobec zależności typu pom (<packaging>pom</packaging>). Dzięki temu możliwe jest zaciągnięcie wszystkich zależności zdefiniowanych w zależności typu pom:

<dependency>
    <groupId>maven</groupId>
    <artifactId>A</artifactId>
    <version>1.0</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

Ten zakres nie żadnego wpływu na tranzytywność zależności.

Warto zajrzeć

1. https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#dependency-scope