Je comprends la différence entre runtime et compile-time et comment faire la différence entre les deux, mais je ne vois tout simplement pas la nécessité de faire une distinction entre les dépendances de compilation et d'exécution.
Les concepts généraux de compilation et d'exécution et les dépendances spécifiques à Maven compile
et à l' runtime
étendue sont deux choses très différentes. Vous ne pouvez pas les comparer directement car ils n'ont pas le même cadre: les concepts généraux de compilation et d'exécution sont larges tandis que les concepts maven compile
et runtime
scope concernent spécifiquement la disponibilité / visibilité des dépendances en fonction du moment: compilation ou exécution.
N'oubliez pas que Maven est avant tout un javac
/ java
wrapper et qu'en Java vous avez un chemin de classe au moment de la compilation que vous spécifiez avec javac -cp ...
et un chemin de classe d'exécution que vous spécifiez avec java -cp ...
.
Il ne serait pas faux de considérer la compile
portée Maven comme un moyen d'ajouter une dépendance à la fois dans la compilation Java et dans le classppath d'exécution (javac
et java
) tandis que la runtime
portée Maven peut être considérée comme un moyen d'ajouter une dépendance uniquement dans le classppath ( javac
) du runtime Java .
Ce dont je m'étouffe, c'est ceci: comment un programme peut-il ne pas dépendre de quelque chose à l'exécution dont il dépendait lors de la compilation?
Ce que vous décrivez n'a aucun rapport avec runtime
et compile
portée.
Cela ressemble plus à la provided
portée que vous spécifiez pour qu'une dépendance dépende de celle au moment de la compilation, mais pas au moment de l'exécution.
Vous l'utilisez car vous avez besoin de la dépendance à compiler mais vous ne voulez pas l'inclure dans le composant packagé (JAR, WAR ou tout autre) car la dépendance est déjà fournie par l'environnement: elle peut être incluse dans le serveur ou tout autre chemin du chemin d'accès aux classes spécifié au démarrage de l'application Java.
Si mon application Java utilise log4j, elle a besoin du fichier log4j.jar pour compiler (mon code s'intégrant avec et invoquant des méthodes membres depuis log4j) ainsi que runtime (mon code n'a absolument aucun contrôle sur ce qui se passe une fois le code dans log4j .jar est exécuté).
Dans ce cas oui. Mais supposons que vous ayez besoin d'écrire un code portable qui s'appuie sur slf4j comme façade devant log4j pour pouvoir passer à une autre implémentation de journalisation plus tard (log4J 2, logback ou toute autre).
Dans ce cas, dans you pom, vous devez spécifier slf4j en tant que compile
dépendance (c'est la valeur par défaut) mais vous spécifierez la dépendance log4j en tant que runtime
dépendance:
<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>
De cette façon, les classes log4j n'ont pas pu être référencées dans le code compilé mais vous pourrez toujours faire référence aux classes slf4j.
Si vous avez spécifié les deux dépendances avec l' compile
heure, rien ne vous empêchera de référencer les classes log4j dans le code compilé et vous pourriez ainsi créer un couplage indésirable avec l'implémentation de la journalisation:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>...</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>...</version>
</dependency>
La runtime
déclaration de dépendance JDBC est une utilisation courante de la portée. Pour écrire du code portable, vous ne voulez pas que le code client puisse faire référence aux classes de la dépendance SGBD spécifique (par exemple: dépendance JDBC PostgreSQL) mais vous voulez tout de même l'inclure dans votre application car au moment de l'exécution, les classes sont nécessaires pour créer l'API JDBC fonctionne avec ce SGBD.