Я розумію різницю між часом виконання та компіляцією та тим, як розрізняти два, але я просто не бачу необхідності розрізняти залежності компіляції від часу та часу виконання.
Загальні поняття часу компіляції та часу виконання, а також специфічні compileта runtimeмасштабні залежності Maven - це дві дуже різні речі. Ви не можете безпосередньо порівнювати їх, оскільки вони не мають однакового кадру: загальні концепції компіляції та часу виконання є широкими, тоді як поняття maven compileта area runtimeстосуються конкретно залежностей / видимості залежно від часу: компіляції чи виконання.
Не забувайте, що Maven - це перш за все a javac/ javawrapper і що у 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 працює з цією СУБД.