Java Dependency Injection design pattern nous permet de supprimer les dépendances codées en dur et de rendre notre application faiblement couplée, extensible et maintenable. Nous pouvons implémenter l’injection de dépendance en java pour déplacer la résolution de dépendance de la compilation à l’exécution.,
injection de dépendance Java
L’injection de dépendance Java semble difficile à saisir avec la théorie, donc je prendrais un exemple simple et ensuite nous verrons comment utiliser le modèle d’injection de dépendance pour obtenir un couplage lâche et une extensibilité dans l’application.
disons que nous avons une application où l’on consomme EmailService
pour envoyer des e-mails. Normalement, nous implémenterions cela comme ci-dessous.
EmailService
classe contient la logique d’envoyer un message électronique à l’adresse électronique du destinataire., Notre code d’application sera comme ci-dessous.
notre code client qui utiliseraMyApplication
classe pour envoyer des messages électroniques sera comme ci-dessous.
à première vue, il ne semble rien de mal à l’implémentation ci-dessus. Mais au-dessus de la logique de code a certaines limites.
-
MyApplication
de classe est responsable d’initialiser le service de courrier électronique et de l’utiliser ensuite. Cela conduit à une dépendance codée en dur. Si nous voulons passer à un autre service de messagerie avancé à l’avenir, il faudra modifier le code dans la classe MyApplication., Cela rend notre application difficile à étendre et si le service de messagerie est utilisé dans plusieurs classes, ce serait encore plus difficile. - Si nous voulons étendre notre application pour fournir une fonctionnalité de messagerie supplémentaire, telle que SMS ou message Facebook, nous devrions écrire une autre application pour cela. Cela impliquera des changements de code dans les classes d’application et dans les classes client.
- tester l’application sera très difficile car notre application crée directement l’instance de service de messagerie. Il n’y a aucun moyen de se moquer de ces objets dans nos classes de test.,
on peut soutenir que nous pouvons supprimer la création d’instance de service de messagerie de la classeMyApplication
en ayant un constructeur qui nécessite un service de messagerie comme argument.
Mais dans ce cas, nous demandons aux applications clientes ou aux classes de test d’initialiser le service de messagerie qui n’est pas une bonne décision de conception.
voyons maintenant comment appliquer le modèle d’injection de dépendance java pour résoudre tous les problèmes avec l’implémentation ci-dessus., L’Injection de dépendances en java nécessite au moins les éléments suivants:
- Les composants de Service doivent être conçus avec une classe ou une interface de base. Il est préférable de préférer des interfaces ou des classes abstraites qui définiraient un contrat pour les services.
- Les classes de consommateurs doivent être écrites en termes d’interface de service.
- classes D’injecteur qui initialiseront les services puis les classes de consommation.
Java Dependency Injection – service Components
pour notre cas, nous pouvons avoirMessageService
qui déclarera le contrat pour les implémentations de service.,
package com.journaldev.java.dependencyinjection.service;public interface MessageService {void sendMessage(String msg, String rec);}
maintenant, disons que nous avons des services de messagerie et de SMS qui implémentent les interfaces ci-dessus.
nos services Java d’injection de dépendances sont prêts et nous pouvons maintenant écrire notre classe consumer.
Java Dependency Injection – service Consumer
Nous ne sommes pas tenus d’avoir des interfaces de base pour les classes consumer mais j’aurai une interfaceConsumer
déclarant un contrat pour les classes consumer.
package com.journaldev.java.dependencyinjection.consumer;public interface Consumer {void processMessages(String msg, String rec);}
mon implémentation de classe de consommation est comme ci-dessous.
notez que notre classe d’application utilise simplement le service., Il n’initialise pas le service qui conduit à une meilleure « séparation des préoccupations ». L’utilisation de l’interface de service nous permet également de tester facilement l’application en se moquant du MessageService et de lier les services à l’exécution plutôt qu’au moment de la compilation.
maintenant, nous sommes prêts à écrire des classes d’injecteur de dépendance java qui initialiseront le service et aussi les classes de consommation.
Java Dependency Injection – Injectors Classes
ayons une interfaceMessageServiceInjector
avec une déclaration de méthode qui renvoie la classeConsumer
.,
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;public interface MessageServiceInjector {public Consumer getConsumer();}
Maintenant, pour chaque service, nous devrons créer un injecteur de classes comme ci-dessous.
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;import com.journaldev.java.dependencyinjection.consumer.MyDIApplication;import com.journaldev.java.dependencyinjection.service.EmailServiceImpl;public class EmailServiceInjector implements MessageServiceInjector {@Overridepublic Consumer getConsumer() {return new MyDIApplication(new EmailServiceImpl());}}
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;import com.journaldev.java.dependencyinjection.consumer.MyDIApplication;import com.journaldev.java.dependencyinjection.service.SMSServiceImpl;public class SMSServiceInjector implements MessageServiceInjector {@Overridepublic Consumer getConsumer() {return new MyDIApplication(new SMSServiceImpl());}}
Maintenant, nous allons voir comment nos applications client va utiliser l’application avec un programme simple.
comme vous pouvez le voir, nos classes d’application ne sont responsables que de l’utilisation du service. Les classes de Service sont créées dans les injecteurs. De plus, si nous devons étendre davantage notre application pour autoriser la messagerie facebook, nous devrons écrire uniquement des classes de Service et des classes d’injecteur.,
l’implémentation d’injection de dépendance a donc résolu le problème de dépendance codée en dur et nous a aidés à rendre notre application flexible et facile à étendre. Voyons maintenant avec quelle facilité nous pouvons tester notre classe d’application en nous moquant des classes d’injecteur et de service.
Java Dependency Injection – JUnit Test Case with Mock Injector and Service
comme vous pouvez le voir, j’utilise des classes anonymes pour simuler les classes d’injecteur et de service et je peux facilement tester mes méthodes d’application., J’utilise JUnit 4 pour la classe de test ci-dessus, alors assurez-vous qu’il est dans le chemin de construction de votre projet si vous exécutez la classe de test ci-dessus.
Nous avons utilisé des constructeurs pour injecter les dépendances dans les classes d’application, une autre façon est d’utiliser une méthode setter pour injecter des dépendances dans les classes d’application. Pour l’injection de dépendance de méthode setter, notre classe d’application sera implémentée comme ci-dessous.
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;import com.journaldev.java.dependencyinjection.consumer.MyDIApplication;import com.journaldev.java.dependencyinjection.service.EmailServiceImpl;public class EmailServiceInjector implements MessageServiceInjector {@Overridepublic Consumer getConsumer() {MyDIApplication app = new MyDIApplication();app.setService(new EmailServiceImpl());return app;}}
l’un des meilleurs exemples d’injection de dépendance setter est Struts2 servlet API Aware interfaces.,
l’utilisation D’une injection de dépendance basée sur un constructeur ou d’un setter est une décision de conception et dépend de vos besoins. Par exemple, si mon application ne peut pas fonctionner du tout sans la classe de service, je préférerais un DI basé sur le constructeur ou bien j’opterais pour un DI basé sur la méthode setter pour ne l’utiliser que lorsque c’est vraiment nécessaire.
L’Injection de dépendances en Java est un moyen de réaliser L’Inversion de contrôle (IoC) dans notre application en déplaçant la liaison d’objets du moment de la compilation au moment de l’exécution., Nous pouvons réaliser le CIO par le modèle D’usine, le modèle de conception de méthode de modèle, le modèle de stratégie et le modèle de localisateur de Service aussi.
Spring Dependency Injection, Google Guice et Java EE CDI frameworks facilitent le processus d’injection de dépendance grâce à L’utilisation de L’API Java Reflection et des annotations java. Tout ce dont nous avons besoin est d’annoter la méthode field, constructor ou setter et de les configurer dans des fichiers ou des classes xml de configuration.,
certains des avantages de L’utilisation de L’Injection de dépendance en Java sont:
- séparation des préoccupations
- réduction de Code standard dans les classes d’application car tout le travail d’initialisation des dépendances est géré par le composant injecteur
- Les composants configurables rendent l’application facilement extensible
- Les tests unitaires
- En cas de surutilisation, cela peut entraîner des problèmes de maintenance car l’effet des modifications est connu lors de l’exécution.,
- L’injection de dépendances en java masque les dépendances de classe de service qui peuvent conduire à des erreurs d’exécution qui auraient été interceptées au moment de la compilation.
c’est tout pour le modèle d’injection de dépendance en java. Il est bon de le savoir et de l’utiliser lorsque nous contrôlons les services.