Je sais qu'il y a beaucoup d'articles qui expliquent comment utiliser CDI en Java EE mais j'ai du mal à comprendre quel avantage cela apporte réellement. Par exemple, supposons que j'ai une classe qui utilise actuellement une instance de Foo. Je pourrais faire
Foo myFoo = new Foo();
ou
// Better, FooFactory might return a mock object for testing
Foo myFoo = FooFactory.getFoo();
Je continue de lire qu'avec CDI je peux faire:
@Inject
Foo myFoo;
mais pourquoi est-ce mieux que l'approche basée sur l'usine précédente? Je suppose qu'il existe un autre cas d'utilisation que je ne connais pas, mais je n'ai pas pu l'identifier.
Si j'ai compris les réponses ci-dessous, le concept est que le framework DI agit comme une fabrique d'objet maître configurée de manière centrale. Est-ce une interprétation raisonnable?
Mise à jour
Depuis, j'ai commencé à apprendre le printemps et cela a maintenant beaucoup plus de sens. Le paragraphe ci-dessous est tiré de Spring in Practice en prenant un exemple d'une classe AccountService
qui, à son tour, utilise une instance de AccountDao
. Je m'excuse pour la longue citation, mais je pense que cela va vraiment au cœur de la raison pour laquelle les ressources injectées offrent quelque chose de plus que l'initialisation standard.
Vous auriez pu construire le AccountService à l'aide du nouveau mot-clé, mais la création d'objets de couche service est rarement aussi simple. Ils dépendent souvent des DAO, des expéditeurs de courrier, SOAP proxies et ainsi de suite. Vous pouvez instancier chacune de ces dépendances par programme dans le constructeur AccountService (ou via l'initialisation statique), mais cela conduit à des dépendances matérielles et les changements en cascade au fur et à mesure qu'ils sont échangés.
De plus, vous pouvez créer des dépendances en externe et les définir sur le AccountService via des méthodes de définition ou des arguments de constructeur. Cela éliminerait les dépendances internes matérielles (tant qu'elles ont été déclarées dans le AccountService par interface), mais vous auriez partout du code d'initialisation en double. Voici comment créer un DAO et le câbler à votre AccountService à la manière Spring:
<bean id="accountDao" class="com.springinpractice.ch01.dao.jdbc.JdbcAccountDao"/>
<bean id="accountService"
class="com.springinpractice.ch01.service.AccountService">
<property name="accountDao" ref="accountDao"/>
</bean>
Après avoir configuré les beans comme ci-dessus, votre programme peut désormais demander une instance de AccountService
au Spring ApplicationContext et le framework Spring DI s'occupe de tout ce qui doit être instancié.
Les personnes qui ont écrit CDI vous ont donné une grande fabrique d'objets; ils ont fait le travail pour vous, mieux que vous. Il est basé sur la configuration ou les annotations XML, vous n'avez donc pas à tout incorporer dans le code.
Les moteurs à injection dépendants, comme Spring, font bien plus que votre usine. Il faudra plus d'une classe d'usine et une ligne de code pour dupliquer tout ce qu'ils offrent.
Bien sûr, vous n'êtes pas obligé de l'utiliser. Vous êtes toujours libre d'inventer votre propre roue. Et vous devriez - si votre but est d'apprendre à fabriquer des roues ou d'éliminer les dépendances.
Mais si vous souhaitez simplement développer des applications, il est préférable d'utiliser les outils que les autres fournissent lorsqu'ils vous donnent un avantage.
article fondateur sur l'injection de dépendance a été écrit par Martin Fowler. Je recommanderais de le lire; c'est toujours génial, huit ans plus tard.
"toujours pas clair sur ce qui est plus"
Voici quelques avantages:
Le but de l'utilisation de l'injection de dépendances est que le code utilisant la chose injectée ne soit pas dépendant de l'usine. Avec votre exemple de code d'usine, il y a un appel de méthode statique incorporé dans votre code qui n'y est pas nécessaire avec l'approche DI.
La chose qui est injectée avec myFoo
ne devrait pas avoir à connaître l'usine.
Il s'agit d'une question importante et subtile sur ce qu'est la programmation d'entreprise.
Le nom est bien choisi: contextes et dépendances.
Le CDI n'a rien à voir avec un code meilleur ou plus propre, il s'agit de s'assurer que les grandes organisations peuvent créer des systèmes logiciels complexes et distribués et partager des données. Il s'agit de s'assurer à 100% que les gouvernements ou autres bureaucraties peuvent distribuer sans discrimination des packages autonomes et bien documentés pour chaque logiciel qu'ils contrôlent. N'oubliez pas que ces jours-ci, pratiquement tous les POJO peuvent être injectés.
Supposons que vous construisez une application client d'une sorte et que vous souhaitiez qu'elle affiche le prénom de l'utilisateur dans le coin.
Les architectes d'entreprise de cette grande entreprise aimeraient que vous ayez cette capacité, mais en tant qu'ingénieur logiciel junior, il n'y a aucune chance de vous remettre les clés de la base de données.
Ils souhaitent également sécuriser les données sur le réseau, mais la société ne paie aucun ingénieur pour réorganiser un client d'authentification chaque fois qu'ils ont besoin de partager un morceau de données.
Ils aimeraient que vous puissiez interroger et mettre à jour ces informations, mais souhaiteraient que les transactions soient traitées à un niveau plus élevé que n'importe quelle application.
Ils aimeraient que vous puissiez tester vos classes avec des simulations triviales dans des blocs de configuration.
Ils souhaiteraient que le couplage entre classes implique un minimum de méthodes statiques.
Et ainsi de suite...
La plupart des JSR ont probablement un "EA aimerait pouvoir ..." enterré quelque part à l'intérieur.
CDI est préféré car il permet aux applications de grandes échelles horizontales et verticales (arbitraires?) De partager des contextes, des dépendances et donc des données.
Selon les mots de Fowler:
"Le problème est de savoir comment puis-je créer ce lien afin que ma classe lister ignore la classe d'implémentation, mais puisse toujours parler à une instance pour faire son travail."
"Mais si nous souhaitons déployer ce système de différentes manières, nous devons utiliser des plugins pour gérer l'interaction avec ces services afin de pouvoir utiliser différentes implémentations dans différents déploiements."
"L'approche utilisée par ces conteneurs est de garantir que tout utilisateur d'un plugin respecte une convention qui permet à un module assembleur distinct d'injecter l'implémentation dans le lister."
En un mot, ils permettent une "commande et un contrôle" centralisés des applications d'entreprise complexes. Java EE est un processus d'abstraction fiable et systématisé et le CDI est une incarnation de celui-ci qui fonctionne si bien qu'il le rend presque invisible. Cela rend l'assemblage d'applications complexes presque trivial.
Deux autres choses:
Notez que CDI existe paisiblement à côté du "modèle de localisateur de service", connu sous le nom de JNDI dans Java EE, ce qui est préférable si le développeur client doit choisir parmi de nombreuses alternatives de type identique.
Le CDI a plus de puissance de feu qu'il n'est nécessaire dans de nombreux cas, en particulier dans les cas non d'entreprise (littéralement).
À un niveau élevé, comme avec la plupart des choses sur CompSci, il offre un niveau d'indirection (ou abstraction) qui autrement être codé en dur dans votre application en tant que Foo myFoo = new Foo();
. Cette indirection entraîne un code faiblement couplé, ce qui rend les choses modulaires, ce qui facilite le remplacement, la maintenance, le test, etc. des classes ou sous-systèmes d'une manière plus simple.
Notez qu'il existe de nombreux modèles et modèles pour l'indirection/abstraction - l'injection de dépendances n'en est qu'un.
L'autre aspect de votre question est "Pourquoi CDI?" - bien, parce que quelqu'un a déjà fait le travail pour vous. Vous pouvez toujours créer vos propres trucs, mais c'est généralement une perte de temps lorsque l'objectif est de construire un système réel qui doit fonctionner sous le budget et sur temps. Pourquoi s'embêter avec l'épicerie et la cuisine quand il y a un chef étoilé Michelin qui est prêt à faire ce travail pour vous?