5 votes

Comment fonctionnent les dépendances de compilation facultatives?

Pendant longtemps, j'ai pensé qu'en Java, on avait soit l'un des deux types de dépendances :

  • Dépendances requises à la compilation (dépendances toujours nécessaires à la compilation)
  • Dépendances potentiellement optionnelles à l'exécution (dépendances pouvant être résolues à l'exécution)

Récemment, j'ai découvert que les dépendances de compilation peuvent également être optionnelles. Par exemple, commons-beanutils est répertorié comme une dépendance optionnelle à la compilation de JXPath.

Comment cela peut-il fonctionner? Une dépendance peut-elle vraiment être utilisée au moment de la compilation tout en restant entièrement optionnelle?

EDIT: Je pourrais ne pas avoir été clair. Je cherche un cas où une dépendance est utilisée à la compilation et est en même temps entièrement optionnelle, ou une explication pourquoi une telle dépendance est impossible.

3voto

Salim Points 1

Une classe peut être compilée vers une interface mais l'implémentation de cette interface n'est pas nécessaire pendant la compilation. L'implémentation est nécessaire pendant l'exécution.

Exemple de commons-logging, JPA, JDBC etc qui sont des cadres, une application peut être compilée en fonction de ceux-ci. Pendant l'exécution, une implémentation est nécessaire pour exécuter le code. Exemples d'implémentations - Common Bean utils, Oracle thin driver, Eclipse link etc.

3voto

Adam Michalik Points 3563

Une citation extensive de la documentation de Maven décrit cela assez clairement :

Les dépendances optionnelles sont utilisées lorsqu'il n'est pas possible (pour une raison quelconque) de diviser un projet en sous-modules. L'idée est que certaines des dépendances ne sont utilisées que pour certaines fonctionnalités du projet et ne seront pas nécessaires si cette fonctionnalité n'est pas utilisée. Idéalement, une telle fonctionnalité serait divisée en un sous-module qui dépend du projet de fonctionnalité de base. Ce nouveau sous-projet n'aurait que des dépendances non optionnelles, car vous en auriez besoin de toutes si vous décidiez d'utiliser la fonctionnalité du sous-projet.

Cependant, comme le projet ne peut pas être divisé (encore une fois, pour une raison quelconque), ces dépendances sont déclarées optionnelles. Si un utilisateur souhaite utiliser une fonctionnalité liée à une dépendance optionnelle, il doit redéclarer cette dépendance optionnelle dans son propre projet. Ce n'est pas la manière la plus claire de gérer cette situation, mais les dépendances optionnelles et les exclusions de dépendances sont des solutions temporaires.

Pourquoi utiliser des dépendances optionnelles ?

Les dépendances optionnelles permettent d'économiser de l'espace et de la mémoire. Elles empêchent les jar problématiques qui violent un accord de licence ou causent des problèmes de chemin de classe d'être regroupés dans un WAR, EAR, fat jar, ou autre.

Comment fonctionnent les dépendances optionnelles ?

Project-A -> Project-B

Le diagramme ci-dessus indique que Project-A dépend de Project-B. Lorsque A déclare B comme une dépendance optionnelle dans son POM, cette relation reste inchangée. C'est comme une construction normale où Project-B sera ajouté dans le chemin de classe de Project-A.

Project-X -> Project-A

Lorsqu'un autre projet (Project-X) déclare Project-A comme une dépendance dans son POM, la nature optionnelle de la dépendance prend effet. Project-B n'est pas inclus dans le chemin de classe de Project-X. Vous devez le déclarer directement dans le POM de Project X pour que B soit inclus dans le chemin de classe de X.

Un exemple pratique : imaginez que vous êtes un développeur d'une bibliothèque/cadre SuperLib qui est construit en tant qu'un superlib.jar. Votre bibliothèque propose plusieurs fonctionnalités. Sa principale fonctionnalité (que la plupart des utilisateurs utilisent) est l'injection de dépendances basée sur une bibliothèque tierce di. Cependant, l'une de vos classes - EmailApi - offre des fonctionnalités pour envoyer des e-mails, en utilisant une bibliothèque tierce email. Comme superlib est un seul artefact, il a besoin à la fois de di et de email pour être compilé.

Maintenant, mettez-vous à la place d'un utilisateur qui utilise superlib. Ils sont intéressés par les fonctionnalités d'injection de dépendances. C'est le rôle principal de votre bibliothèque, donc la dépendance entre superlib et di ne serait pas optionnelle.

Cependant, la plupart des utilisateurs ne sont pas intéressés à envoyer des e-mails et peuvent être gênés par le fait d'avoir une bibliothèque email inutile et ses dépendances ajoutées à leur application (ce qui augmentera la taille de leur application et pourrait provoquer un conflit de versions de dépendances entre les dépendances de email et celles de l'application de l'utilisateur). Par conséquent, vous marqueriez la dépendance sur email comme optionnelle. Tant que l'utilisateur n'utilise pas votre classe EmailApi, tout se passera bien. Cependant, s'ils utilisent EmailApi, ils auront besoin de la dépendance email, sinon l'application échouera à l'exécution avec une ClassNotFoundException pour la classe de email qui serait référencée dans EmailApi. L'utilisateur de votre bibliothèque devra ajouter explicitement la dépendance email dans leur POM.

Voir aussi Quand utiliser true et quand utiliser provided.

-1voto

Alex Chernyshev Points 921

Ce que vous avez décrit est en fait une fonctionnalité de Maven, l'outil de construction, mais pas de Java lui-même. Sans outils de construction, en utilisant simplement 'javac', vous devez spécifier toutes les classes ou interfaces directement utilisées dans votre code. Bien sûr, il existe des options pour le chargement de classes dynamique et même la compilation en temps d'exécution, mais ce n'est pas le sujet.

Un des cas d'utilisation avec une séparation entre l'interface et l'implémentation est décrit dans la réponse précédente, un autre cas populaire est basé sur la numérisation du classpath : si une classe spécifique est présente dans le classpath et/ou a une annotation spécifique - un module optionnel sera chargé.

C'est ainsi que les modules Spring Boot sont chargés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X