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 compileund runtimeBereichsabhä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- compileund runtimeScope-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/ javawrapper 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- compileBereich als eine Möglichkeit zu betrachten, eine Abhängigkeit sowohl in der Java-Kompilierung als auch im Laufzeitklassenpfad hinzuzufügen (javacund java) während der Maven- runtimeBereich 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 runtimeund compileUmfang.
Es sieht eher nach dem providedBereich 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 compileAbhängigkeit angeben (dies ist die Standardeinstellung), aber Sie geben die log4j-Abhängigkeit als runtimeAbhä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 compileZeit 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 runtimeGü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.