Ich verstehe den Unterschied zwischen Laufzeit und Kompilierungszeit und wie man zwischen beiden unterscheidet, aber ich sehe keine Notwendigkeit, zwischen Abhängigkeiten von Kompilierungszeit und Laufzeit zu unterscheiden.
Die allgemeinen Konzepte zur Kompilierungs- und Laufzeit sowie die Maven-spezifischen compile
und runtime
Bereichsabhängigkeiten sind zwei sehr unterschiedliche Dinge. Sie können sie nicht direkt vergleichen, da diese nicht denselben Rahmen haben: Die allgemeinen Kompilierungs- und Laufzeitkonzepte sind breit gefächert, während es bei den Maven- compile
und runtime
Scope-Konzepten speziell um die Verfügbarkeit / Sichtbarkeit von Abhängigkeiten je nach Zeit geht: Kompilierung oder Ausführung.
Vergessen Sie nicht, dass Maven vor allem ein javac
/ java
wrapper ist und dass Sie in Java einen Klassenpfad zur Kompilierungszeit haben, mit dem Sie angeben, javac -cp ...
und einen Laufzeitklassenpfad, mit dem Sie angeben java -cp ...
.
Es wäre nicht falsch, den Maven- compile
Bereich als eine Möglichkeit zu betrachten, eine Abhängigkeit sowohl in der Java-Kompilierung als auch im Laufzeitklassenpfad hinzuzufügen (javac
und java
) während der Maven- runtime
Bereich als eine Möglichkeit angesehen werden kann, eine Abhängigkeit nur im Java-Laufzeitklassenpfad ( javac
) hinzuzufügen .
Woran ich ersticke, ist Folgendes: Wie kann ein Programm zur Laufzeit nicht von etwas abhängen, von dem es während der Kompilierung abhängt?
Was Sie beschreiben, hat keine Beziehung zu runtime
und compile
Umfang.
Es sieht eher nach dem provided
Bereich aus, den Sie angeben, damit eine Abhängigkeit zur Kompilierungszeit, jedoch nicht zur Laufzeit davon abhängt.
Sie verwenden es, wenn Sie die Abhängigkeit zum Kompilieren benötigen, möchten es jedoch nicht in die gepackte Komponente (JAR, WAR oder andere) aufnehmen, da die Abhängigkeit bereits von der Umgebung bereitgestellt wird: Sie kann auf dem Server oder in einer anderen Komponente enthalten sein Pfad des Klassenpfads, der beim Starten der Java-Anwendung angegeben wurde.
Wenn meine Java-App log4j verwendet, benötigt sie die Datei log4j.jar zum Kompilieren (mein Code integriert und ruft Mitgliedsmethoden aus log4j heraus auf) sowie zur Laufzeit (mein Code hat absolut keine Kontrolle darüber, was passiert, wenn Code in log4j einmal vorhanden ist .jar wird ausgeführt).
In diesem Fall ja. Angenommen, Sie müssen einen tragbaren Code schreiben, der auf slf4j als Fassade vor log4j basiert, um später zu einer anderen Protokollierungsimplementierung wechseln zu können (log4J 2, logback oder eine andere).
In diesem Fall müssen Sie in Ihrem pom slf4j als compile
Abhängigkeit angeben (dies ist die Standardeinstellung), aber Sie geben die log4j-Abhängigkeit als runtime
Abhängigkeit an:
<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>
Auf diese Weise konnten die log4j-Klassen im kompilierten Code nicht referenziert werden, Sie können jedoch weiterhin auf slf4j-Klassen verweisen.
Wenn Sie die beiden Abhängigkeiten mit der compile
Zeit angegeben haben, hindert Sie nichts daran, log4j-Klassen im kompilierten Code zu referenzieren, und Sie könnten so eine unerwünschte Kopplung mit der Protokollierungsimplementierung erstellen:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
</dependency>
Eine häufige Verwendung des runtime
Gültigkeitsbereichs ist die JDBC-Abhängigkeitsdeklaration. Um portablen Code zu schreiben, möchten Sie nicht, dass der Clientcode auf Klassen der spezifischen DBMS-Abhängigkeit verweist (z. B. PostgreSQL JDBC-Abhängigkeit), aber Sie möchten, dass er trotzdem in Ihre Anwendung aufgenommen wird, da zur Laufzeit die Klassen erstellt werden müssen Die JDBC-API funktioniert mit diesem DBMS.