Cet article est destiné à apporter des éléments de réponses sur l’injection de dépendance avec CDI. L’implémentation de référence (développée par JBoss) sera utilisée : il s’agit de Weld.
L’injection de dépendance, souvent liée à l’inversion de contrôle, est un mécanisme permettant de réaliser des relations de dépendance dynamiquement, entre classes, en utilisant un fichier de configuration, ou bien des annotations. Avec Weld, les annotations sont utilisées afin d’indiquer les points d’injections au sein de l’application.
Weld est un framework d’injection de dépendances fortement typé. C’est à dire que les classes injectées au niveau des points d’injection vont être résolues en fonction de leur type, et non de leur nom.
Exemple :
|
1 2 3 4 5 |
public class MyBean { @Inject private Clazz1 clazz1; @Inject private Clazz2 clazz2; /* Getters ans setters */ } |
Lors de la résolution des injections, Weld va rechercher dans ses scopes une instance de Clazz1 et de Clazz2. Si aucune instance n’existe encore, Weld va en créer une nouvelle afin de l’injecter au niveau de ces points d’injection.
Les types d’injection
Weld propose trois types d’injections :
-
Les injections par attribut :
12345public class MyBean {@Inject private Clazz1 attr1;@Inject private Clazz2 attr2;/* Getters ans setters */} -
Les injections par constructeur :
123456public class MyBean {@Injectpublic MyBean(Clazz1 attr1) {...}} -
Les injections par méthode :
123456public class MyBean {@Injectpublic void process(Clazz1 attr1) {...}}
Les producers
Afin de pouvoir résoudre les classes à injecter, Weld a besoin de connaitre la contre-partie de ces points d’injection. Ces méthodes, ou champs, sont appelés Producers. Ils doivent être surmontés de l’annotation @Produces.
Producer par méthode :
|
1 2 3 4 5 6 |
public class MyProducer { @Produces public String stringProducer() { return "Chaîne de caractères injectée"; } } |
Producer par attribut :
|
1 2 3 4 |
public class MyProducer { @Produces private String s = "Chaîne de caractères injectée"; } |
Nous pouvons alors réaliser l’injection suivante :
|
1 2 3 4 5 6 |
public class MyBean { @Inject public void printString(String s) { System.out.println(s); } } |
Weld sera en mesure d’associer automatiquement l’injection à son producer (résolution par Type) !
Attention : Si toutefois il existe 2 producer renvoyant le même Type d’objet, il y aura conflit d’injection. C’est à dire que Weld ne sera pas en mesure de déterminer quel producer doit être utilisé. Je vous renvoie alors vers les @Qualifier et les Alternatives, qui pourront éventuellement être l’objet d’un prochain post.
Exemple de conflit d’injection à deployment-time :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public class MyProducers { @Produces private String s1 = "Je suis la chaîne 1"; @Produces public String getString() { return "Je suis la chaîne 2"; } } public class MyBean { @Inject private String s; /* Conflit d'injection : Weld ne peut pas déterminer le producer à utiliser */ } |
Une correction possible pourrait être , en utilisant les qualifiers :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public class MyProducers { @Produces @String1 private String s1 = "Je suis la chaîne 1"; @Produces @String2 public String getString() { return "Je suis la chaîne 2"; } } @Qualifier @Target({TYPE, METHOD, PARAMETER, FIELD}) @Retention(RUNTIME) public @interface String1 {} public class MyBean { @Inject @String1 private String s; /* Weld utilisera le producer associé au qualifier @String1 */ } |
L’annotation @Named
Cette annotation permet de rendre disponible une instance d’un bean managé à travers une EL (Expression Language), au sein d’une page JSP ou Facelets (XHTML).
Le conteneur de bean Weld surcharge le conteneur de bean JSF dans le cadre d’une utilisation conjointe de ces deux framework. Ainsi, les annotation JSF 2.0 @ManagedBean peuvent être remplacées par @Named.
|
1 2 3 4 |
@Named public class MyBean { ... } |
Dans ce cas, le bean sera accessible via l’EL
|
1 |
#{myBean} |
Mais l’annotation peut également être paramétrée d’un nom à donner au bean à travers l’EL :
|
1 2 3 4 |
@Named("myNamedBean") public class MyBean { ... } |
Dans cet autre cas, le bean sera accessible via l’EL
|
1 |
#{myNamedBean} |

Bonjour,
Je ne suis pas (encore) très familier avec l’injection de dépendances, donc j’ai trouvé cet article très interessant, mais je me demandais quelles étaient les différences entre la jsr 299 (weld) et la 330 (guice). Il me semble que les annotations principales sont les mêmes, donc pourquoi 2 jsr ?
Thomas
Salut Thomas,


La JSR 330 est née d’une demande (de Google) de simplification de la JSR 299 (qui comprend beaucoup plus de choses que l’@Inject, comme les @Observers, les @Decorator ou les @Interceptor). On peut considérer, je pense, que la JSR 299 est composée de la JSR 330.
L’idée de la JSR 299 est d’avoir une solution légère d’injection de dépendance, ce qui n’est pas le cas avec CDI, qui reste une grosse mécanique, mais très puissante !
A ce sujet, je t’invite à lire cet article pour comprendre le contexte de création de la JSR 330
Si CDI t’intéresse, tu peux trouver la documentation de Weld (l’implémentation de référence) ici
N’hésite pas à visiter notre blog régulièrement, tu y trouveras des billets sur CDI que j’affectionne particulièrement
Mathieu
Merci beaucoup pour ta réponse Mathieu. Le JCP c’est un peu “Dallas”…