Я понимаю разницу между временем выполнения и временем компиляции и как их различать, но я просто не вижу необходимости проводить различие между зависимостями времени компиляции и времени выполнения.
Общие концепции времени компиляции и времени выполнения, а также зависимости Maven compile
и runtime
области видимости - это две очень разные вещи. Вы не можете напрямую сравнивать их, поскольку у них разные рамки: общие концепции компиляции и времени выполнения широки, в то время как концепции maven compile
и runtime
scope касаются, в частности, доступности / видимости зависимостей в зависимости от времени: компиляция или выполнение.
Не забывайте, что Maven - это прежде всего javac
/ java
оболочка, и что в Java у вас есть путь к классам времени компиляции, который вы указываете, javac -cp ...
и путь к классам времени выполнения, который вы указываете java -cp ...
.
Было бы правильно рассматривать область Maven compile
как способ добавления зависимости как в компиляцию Java, так и в runtime classppath (javac
и java
), в то время как область Maven runtime
можно рассматривать как способ добавления зависимости только в среде выполнения Java classppath ( javac
).
Я задыхаюсь от этого: как программа может не зависеть во время выполнения от чего-то, от чего она зависела во время компиляции?
То , что вы описали не имеет никакого отношения с runtime
и compile
объемом.
Похоже, что provided
область видимости, которую вы указываете, зависит от зависимости во время компиляции, но не во время выполнения.
Вы используете его, поскольку вам нужна зависимость для компиляции, но вы не хотите включать ее в упакованный компонент (JAR, WAR или любой другой), потому что зависимость уже предоставлена средой: она может быть включена в сервер или любой другой путь к пути к классам, указанному при запуске приложения Java.
Если мое приложение Java использует log4j, то ему нужен файл log4j.jar для компиляции (мой код интегрируется с методами-членами и вызывает их изнутри log4j), а также во время выполнения (мой код не имеет абсолютно никакого контроля над тем, что происходит, когда код внутри log4j .jar запущен).
В этом случае да. Но предположим, что вам нужно написать переносимый код, который полагается на slf4j в качестве фасада перед log4j, чтобы иметь возможность позже переключиться на другую реализацию ведения журнала (log4J 2, logback или любую другую).
В этом случае в вашем pom вам нужно указать slf4j как compile
зависимость (это значение по умолчанию), но вы укажете зависимость log4j как runtime
зависимость:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
<scope>runtime</scope>
</dependency>
Таким образом, на классы log4j нельзя ссылаться в скомпилированном коде, но вы все равно сможете ссылаться на классы slf4j.
Если вы указали две зависимости со compile
временем, ничто не помешает вам ссылаться на классы log4j в скомпилированном коде, и вы можете создать нежелательную связь с реализацией ведения журнала:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
</dependency>
Обычно runtime
область видимости используется в объявлении зависимости JDBC. Чтобы писать переносимый код, вы не хотите, чтобы клиентский код мог ссылаться на классы конкретной зависимости СУБД (например, зависимость PostgreSQL JDBC), но вы все равно хотите включить его в свое приложение, поскольку во время выполнения классы необходимы для создания JDBC API работает с этой СУБД.