Java Dependency Injection návrhový vzor umožňuje nám odstranit pevně závislostí, a aby naše aplikace volně vázané, rozšiřitelný a udržovatelný. Můžeme implementovat aplikaci dependency injection v Javě pro přesun rozlišení závislosti z doby kompilace do runtime.,
Java Dependency Injection
Java Dependency injection se zdá těžké pochopit s teorií, tak bych si jednoduchý příklad, a pak budeme vidět, jak používat dependency injection vzor, jak dosáhnout volné vazby, a rozšiřitelnost v aplikaci.
řekněme, že máme aplikaci, kde konzumujeme EmailService
pro odesílání e-mailů. Normálně bychom to implementovali níže.
EmailService
třída má logiku poslat e-mailovou zprávu na e-mailovou adresu příjemce., Náš aplikační kód bude jako níže.
náš klientský kód, který bude používatMyApplication
třída pro odesílání e-mailových zpráv bude jako níže.
na první pohled se zdá, že s výše uvedenou implementací není nic špatného. Ale nad logikou kódu má určitá omezení.
-
MyApplication
třída je zodpovědná za inicializaci e-mailové služby a její použití. To vede k hard-kódované závislosti. Pokud chceme v budoucnu přejít na jinou pokročilou e-mailovou službu, bude to vyžadovat změny kódu ve třídě MyApplication., To ztěžuje rozšíření naší aplikace a pokud je e-mailová služba používána ve více třídách, pak by to bylo ještě těžší. - pokud chceme rozšířit naši aplikaci o další funkci zasílání zpráv, jako je SMS nebo zpráva Facebook, musíme pro to napsat jinou aplikaci. To bude zahrnovat změny kódu ve třídách aplikací a také v třídách klientů.
- testování aplikace bude velmi obtížné, protože naše aplikace přímo vytváří instanci e-mailové služby. Neexistuje žádný způsob, jak bychom mohli zesměšňovat tyto objekty v našich testovacích třídách.,
Jeden může argumentovat, že můžeme odstranit e-mailové služby, například vytvoření z MyApplication
třídy tím, že konstruktor vyžaduje e-mailové služby jako argument.
ale v tomto případě žádáme klientské aplikace nebo testovací třídy o inicializaci e-mailové služby, která není dobrým rozhodnutím o návrhu.
nyní se podívejme, jak můžeme použít java dependency injection pattern k vyřešení všech problémů s výše uvedenou implementací., Aplikace Dependency Injection v Javě vyžaduje alespoň následující: komponenty služby
- by měly být navrženy se základní třídou nebo rozhraním. Je lepší upřednostňovat rozhraní nebo abstraktní třídy, které by definovaly smlouvu o službách.
- třídy spotřebitelů by měly být zapsány z hlediska rozhraní služeb.třídy vstřikovačů
- , které inicializují služby a poté třídy spotřebitelů.
Java Dependency Injection – Komponent Služby
Pro náš případ, můžeme mít MessageService
, který bude deklarovat zakázky na služby implementace.,
package com.journaldev.java.dependencyinjection.service;public interface MessageService {void sendMessage(String msg, String rec);}
nyní řekněme, že máme e-mailové a SMS služby, které implementují výše uvedená rozhraní.
naše služby dependency injection java jsou připraveny a nyní můžeme napsat naši spotřebitelskou třídu.
Java Dependency Injection – Služby pro Spotřebitele
není nutné mít základní rozhraní pro spotřebitele tříd, ale budu mít Consumer
rozhraní deklarovat smlouva pro spotřebitelské třídy.
package com.journaldev.java.dependencyinjection.consumer;public interface Consumer {void processMessages(String msg, String rec);}
Moje implementace spotřebitelské třídy je jako níže.
Všimněte si, že naše třída aplikací právě používá službu., Neinicializuje službu, která vede k lepšímu „oddělení obav“. Také použití rozhraní služby nám umožňuje snadno otestovat aplikaci zesměšňovat MessageService a svázat služby za běhu, spíše než čas kompilace.
Nyní jsme připraveni napsat java dependency injector tříd, které se bude inicializovat, a také služby spotřebitelské třídy.
Java Závislost Vstřikování – vstřikovací ventily Třídy
rozhraní MessageServiceInjector
s metodou prohlášení, že vrátí Consumer
třídy.,
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;public interface MessageServiceInjector {public Consumer getConsumer();}
nyní pro každou službu budeme muset vytvořit třídy vstřikovačů, jako je níže.
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());}}
nyní se podívejme, jak naše klientské aplikace budou používat aplikaci s jednoduchým programem.
jak můžete vidět, že naše třídy aplikací jsou zodpovědné pouze za používání služby. Servisní třídy jsou vytvořeny v vstřikovačích. Také pokud budeme muset dále rozšířit naši aplikaci, abychom umožnili zasílání zpráv facebook, budeme muset psát pouze třídy služeb a třídy vstřikovačů.,
takže implementace aplikace dependency injection vyřešila problém s hard-kódovanou závislostí a pomohla nám učinit naši aplikaci flexibilní a snadno rozšiřitelnou. Nyní se podívejme, jak snadno můžeme otestovat naši aplikační třídu zesměšňováním tříd vstřikovačů a služeb.
Java Dependency Injection-JUnit Test Case with Mock Injector and Service
jak můžete vidět, že používám anonymní třídy k zesměšňování tříd vstřikovačů a služeb a mohu snadno otestovat své aplikační metody., Používám JUnit 4 pro výše uvedenou testovací třídu, takže se ujistěte, že je ve vaší cestě k sestavení projektu, pokud běžíte nad testovací třídou.
použili jsme konstruktory k aplikaci závislostí do aplikačních tříd, dalším způsobem je použití metody setter pro aplikaci závislostí do aplikačních tříd. U aplikace setter method dependency injection bude naše aplikační třída implementována jako níže.
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;}}
jedním z nejlepších příkladů aplikace setter dependency injection je rozhraní Struts2 Servlet API Aware.,
zda se má použít injection dependency injection založené na konstruktoru nebo setru, je rozhodnutí o návrhu a závisí na vašich požadavcích. Například, pokud moje aplikace nemůže fungovat bez služby třídy pak bych raději konstruktoru na základě DI, jinak bych jít pro setter metoda založená DI používat pouze když je to opravdu potřeba.
Dependency Injection v Javě je způsob, jak dosáhnout Inverze řízení (IoC)v naší aplikaci přesunutím vazeb objektů z doby kompilace do běhu., Můžeme dosáhnout IoC prostřednictvím továrního vzoru, vzor návrhu metody šablony, vzor strategie a vzor lokátoru služeb.
injekce jarní závislosti, rámce Google Guice a Java EE CDI usnadňují proces vstřikování závislostí pomocí Java Reflection API a Java anotací. Vše, co potřebujeme, je anotovat metodu pole, konstruktoru nebo setteru a nakonfigurovat je v konfiguračních souborech nebo třídách xml.,některé z výhod použití aplikace Dependency Injection v Javě jsou:
- oddělení obav
- redukce kódu Boilerplate v aplikačních třídách, protože všechny práce na inicializaci závislostí jsou řešeny komponentou injector
- konfigurovatelné komponenty činí aplikaci snadno rozšiřitelnou
- testování jednotek je snadné s falešnými objekty
nevýhody Java Dependency Injection Injection
Java Dependency injection má některé nevýhody také:
- pokud je nadužíváno, může to vést k problémům s údržbou, protože účinek změn je znám za běhu.,
- injekce závislostí v jazyce java skrývá závislosti třídy služeb, které mohou vést k chybám runtime, které by byly zachyceny v době kompilace.
to je vše pro vzor injekce závislosti v Javě. Je dobré to vědět a používat, když máme služby pod kontrolou.