Я понимаю разницу между временем выполнения и временем компиляции и тем, как их различать, но я просто не вижу необходимости проводить различие между зависимостями времени компиляции и времени выполнения.
Общие понятия времени компиляции и времени выполнения и специфичные для Maven зависимости compile
и runtime
области видимости - это две очень разные вещи.Вы не можете напрямую сравнивать их, так как они не имеют одинакового фрейма: общие концепции компиляции и времени выполнения являются широкими, в то время как концепции областей действия maven compile
и runtime
конкретно касаются доступности / видимости зависимостей в зависимости от времени: компиляция иливыполнение.
Не забывайте, что Maven - это прежде всего оболочка javac
/ java
, а в Java у вас есть путь к классу времени компиляции, который вы указываете с помощью javac -cp ...
, и путь к классу времени выполнения, который вы указываете с помощью java -cp ...
.
Было бы неплохо рассматривать область действия Maven compile
как способ добавления зависимости как в компиляцию Java, так и в classppath времени выполнения (javac
и java
), тогда как область действия Maven runtime
можетможно рассматривать как способ добавления зависимости только в classppath времени выполнения Java (javac
).
То, что я задыхаюсь, заключается в следующем: как программа может не зависеть от чего-либо во время выполнения, от которого она зависела во время компиляции?
То, что вы описываете, не имеет никакого отношения к runtime
и compile
scope.
Похоже, больше к области provided
, которую вы указываете для зависимости, зависит отэто во время компиляции, но не во время выполнения.
Вы используете это, поскольку вам нужна зависимость для компиляции, но вы не хотите включать ее в упакованный компонент (JAR, WAR или любой другой), потому что зависимость уже предоставляется средой: он может быть включен в сервер или в любой путь пути к классу, указанный при запуске приложения Java.
Если мое Java-приложение использует log4j, то ему необходим файл log4j.jar для компиляции (мой код интегрируется с методами-членами и вызывается изнутри log4j), а также во время выполнения (мой код имеет абсолютнонет контроля над тем, что происходит после запуска кода внутри log4j.jar).
В этом случае да.Но предположим, что вам нужно написать переносимый код, который опирается на slf4j как фасад перед log4j, чтобы иметь возможность переключиться на другую реализацию ведения журнала позже (log4J 2, logback или любую другую).
В этом случае вы помнитенеобходимо указать 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 работает с этой СУБД.