Я розумію різницю між часом виконання та компіляцією та тим, як розрізняти два, але я просто не бачу необхідності розрізняти залежності компіляції від часу та часу виконання.
Загальні поняття часу компіляції та часу виконання, а також специфічні compile
та runtime
масштабні залежності Maven - це дві дуже різні речі. Ви не можете безпосередньо порівнювати їх, оскільки вони не мають однакового кадру: загальні концепції компіляції та часу виконання є широкими, тоді як поняття maven compile
та area runtime
стосуються конкретно залежностей / видимості залежно від часу: компіляції чи виконання.
Не забувайте, що Maven - це перш за все a javac
/ java
wrapper і що у Java у вас є компільований часовий шлях компіляції, який ви вказуєте, javac -cp ...
і клас маршруту виконання, який ви вказуєте java -cp ...
.
Неправильно було б розглядати compile
область Maven як спосіб додати залежність як до компіляції Java, так і до класу виконання програми (javac
та java
) хоча runtime
область Maven може розглядатися як спосіб додати залежність лише у Java Ruppime classppath ( javac
).
Мене задихається такий: як програма може не залежати від чогось під час виконання, від якого вона залежала під час компіляції?
Те, що ви описуєте, не має жодного стосунку runtime
та compile
сфери застосування.
Це схоже більше на 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), але ви хочете, щоб все-таки включити його у свою програму, оскільки під час виконання потрібні класи, щоб зробити API JDBC працює з цією СУБД.