Vous êtes sur la page 1sur 5

Présentation de l'injection de

dépendance
Principes
Lorsque l'on développe un programme en java, afin d'éviter de tout avoir dans un seul
fichier, le développeur écrit plusieurs classes (une classe par fichier). Cela permet non
seulement d'assurer une meilleure lisibilité mais aussi une meilleure maintenance.

Seulement lorsque l'on passe en plusieurs classes, on souhaite pouvoir enlever une classe et
la remplacer par une autre classe. Cela n'est malheuresement pas possible en java de
base, il faut passer par de l'injection de dépendance. Cela permet entre autre "d'échanger"
une classe par une autre et d'avoir plusieurs configurations d'application.

Il existe 4 types d'injections de dépendances :

 Injection par constructeur


 Injection par interface
 Injection par mutateur
 Injection par champs
On peut faire de l'injection de dépendance à la main sans utiliser d'outils ou bien utiliser
des frameworks (voir plus bas)

Histoire

Tout d'abord :
Lors de la séparation d'un code en plusieurs classes, nous avons une dépendance directe
d'une classe a une autre. Nous séparons le code général en une classe A et une classe B. La
classe A doit utiliser une méthode de la classe B.

Cela se fait donc dans le code de A comme suit :

public class A {
   public static void main(String[] args)
      B b = new B();
      b.someMethod();
   }
}

Avantages :
 Rapide à developperInconvénients :
 Statique
 Disperse les dépendances dans le code
Les interfaces :
Le java fournit un moyen de simplifier la gestion des dépendances : l'Interface. Les
interfaces en java permettent de définir des méthodes et leurs paramètres sans en définir
le code. Ces interfaces sont ensuites implémentées par les classes dont on dépend.
Ici, on crée une interface I définissant la méthode someMethod() et la classe A ne dépend
donc plus de B directement mais de I qui peut être implémenté par n'importe quelle autre
classe.

Cela se fait donc dans le code de A comme suit :

public class A {
   public static void main(String[] args)
      I b = new B();
      b.someMethod();
   }
}
Comme nous pouvons le constater, nous avons gardé le new ce qui fait qu'il reste une
dépendance indirecte dans A.

Avantages :
 Toujours rapide à developper
 Possibilité de changer d'implémentationInconvénients :
 Dépendance toujours là
 Disperse les dépendances dans le code
Les Factories :
Afin d'avoir du code java propre, la comunauté java à instauré des principes de
programmations. Ces principes sont appelés des Design Pattern. Parmis ces design pattern
on peut trouver le pattern factory. Ce pattern permet d'avoir une classe factory qui va
gérer les dépendances. Cette factory possède des méthodes qui vont instancier la
dépendance (ici B) et la retourner. Chaque fois qu'une dépendance devra être résolue
(besoin d'un objet de type I) , la classe appelante utilisera la factory.
Cela se fait donc dans le code de factory comme suit :

public class factory {


   public I getDependency()
      return new B();
   }
}

Et dans A :

public class A {
   public static void main(String[] args) {
      I b = new factory().getDependency();
      b.someMethod();
   }
}

Avantages :
 Possibilité de changer d'implémentation
 Centralisation des dépendances à un seul endroitInconvénients :
 Lourd à utiliser
 Pas connu par tous les développeurs
L'injection par constructeur :
Les developpement d'applications java ayant besoin de plus en plus de tests, l'injection par
factory ne suffit plus. Effectivement, cette dernière ne permet pas d'avoir une
configuration de production et une configuration de tests. Une solution pour permettre de
choisir le mode de lancement (configuration) est de passer l'implémentation directement
dans le constructeur de notre classe (ici A)

Cela se fait donc dans le code de A comme suit :

public class A {
   I inst;

   public A(I inst) {


      this.inst=inst;
   }

   public void doWork() {


      inst.someMethod();
   }
}

Et dans la classe appelante :

public static void main(String[] args) {


   A a = new A(factory().getDependency());
   a.doWork();
}

Avantages :
 Possibilité de changer d'implémentation
 Possibilité de gérer les dépendances au plus haut de l'applicationInconvénients :
 Dispersion du code (classes et sous classes)
Cette méthode est l'une des plus "propre" et des plus pratique pour faire de l'injection de
dépendance. Cependant, des frameworks existent pour éviter au developpeur de gérer ses
injections.

Les frameworks
Il existe peu de frameworks pour faire de l'injection de dépendances, je ne présenterai que
les 2 plus grands frameworks et les plus récents sur ce site.

Voici certains frameworks recencés à ce jour :


 PicoContainer (injection par constructeur)
 Excalibur (injection par Interface): anciennement connu sous le nom d'Avalon
 Spring IoC (injection par mutateur)
 Google Guice (injection par champs et constructeur)
Les frameworks PicoContainer et Excalibur (sous son ancien nom Avalon) ont été les
premiers à apparaitre comme frameworks d'injection de dépendance. Guice et Spring
étants très récents
Voici un rapide résumé du fonctionnement des frameworks PicoContainer et Excalibur

PicoContainer :
PicoContainer a un fonctionnement proche de l'injection par constructeur vue ci dessus. Ce
dernier requiert que la classe utilisant la dépendance ai un constructeur permettant de
définir l'implémentation. L'application instancie ensuite le picoContainer (par
défaut DefaultPicoContainer) et lui faire enregistrer quelle implémentation est associée a
quelle interface.
Pour finir, le framework se charge de construire les élements qui ont besoin d'utiliser des
dépendances.

Excalibur :
Excalibur fonctionne via de l'injection par interface. Il est donc requis de crée une
interface qui va permettre d'injection la dépendance (en plus de l'interface qui définit les
méthodes de la dépendance). Cette interface possèdera une méthode permettant de
mettre en place l'implémentation de la dépendance.
Notre classe devra implémenter cette interface et utilisera le code de la méthode pour
définir son implémentation de la dépendance. Elle pourra ensuite utiliser cette dernière
pour n'importe quelle autre méthode.
L'application instancie ensuite un Container dans lequel est enregistré.