Java Dependency Injection Design pattern tillåter oss att ta bort de hårdkodade beroenden och göra vår ansökan löst kopplad, utdragbar och underhållbar. Vi kan implementera dependency injection i java för att flytta beroendeupplösningen från kompileringstid till runtime.,
Java Dependency Injection
Java Dependency injection verkar svårt att förstå med teorin, så jag skulle ta ett enkelt exempel och då kommer vi att se hur man använder beroendeinsprutningsmönster för att uppnå lös koppling och förlängbarhet i applikationen.
låt oss säga att vi har ett program där vi konsumerarEmailService
för att skicka e-post. Normalt skulle vi genomföra detta som nedan.
EmailService
klassen har logiken att skicka ett e-postmeddelande till mottagarens e-postadress., Vår applikationskod kommer att vara som nedan.
vår kundkod som kommer att användaMyApplication
klass för att skicka e-postmeddelanden kommer att vara som nedan.
vid första anblicken verkar det inget fel med ovanstående genomförande. Men ovanför kodlogiken har vissa begränsningar.
-
MyApplication
klassen ansvarar för att initiera e-posttjänsten och sedan använda den. Detta leder till hårdkodat beroende. Om vi vill byta till någon annan avancerad e-posttjänst i framtiden, kommer det att kräva kodändringar i myapplication klass., Detta gör vår ansökan svårt att förlänga och om e-posttjänst används i flera klasser så skulle det vara ännu svårare. - Om vi vill utöka vår ansökan för att ge en extra meddelandefunktion, till exempel SMS eller Facebook-meddelande, skulle vi behöva skriva en annan applikation för det. Detta kommer att innebära kodändringar i applikationsklasser och i klientklasser också.
- testa programmet kommer att bli mycket svårt eftersom vår ansökan direkt skapar e-posttjänstinstansen. Vi kan inte håna föremålen i våra Testkurser.,
man kan hävda att vi kan ta bort skapandet av e-posttjänstinstans från MyApplication
– klassen genom att ha en konstruktör som kräver e-posttjänst som ett argument.
men i det här fallet ber vi klientapplikationer eller testklasser att initiera e-posttjänsten som inte är ett bra designbeslut.
låt oss nu se hur vi kan tillämpa java dependency injection pattern för att lösa alla problem med ovanstående implementering., Beroendeinjektion i java kräver minst följande:
- Servicekomponenter ska utformas med basklass eller gränssnitt. Det är bättre att föredra gränssnitt eller abstrakta klasser som skulle definiera kontrakt för tjänsterna.
- konsumentklasser ska skrivas när det gäller servicemenskap.
- injektor klasser som kommer att initiera tjänsterna och sedan konsument klasser.
Java Dependency Injection – Service Components
för vårt fall kan vi haMessageService
som kommer att förklara kontraktet för tjänsteimplementeringar.,
package com.journaldev.java.dependencyinjection.service;public interface MessageService {void sendMessage(String msg, String rec);}
låt oss nu säga att vi har e-post-och SMS-tjänster som implementerar ovanstående gränssnitt.
våra beroendeinjektion java-tjänster är redo och nu kan vi skriva vår konsumentklass.
Java Dependency Injection – Service Consumer
vi behöver inte ha basgränssnitt för konsumentklasser men jag kommer att ha ETTConsumer
gränssnitt som förklarar kontrakt för konsumentklasser.
package com.journaldev.java.dependencyinjection.consumer;public interface Consumer {void processMessages(String msg, String rec);}
implementeringen av min konsumentklass är som nedan.
Observera att vår applikationsklass bara använder tjänsten., Det initierar inte tjänsten som leder till bättre ”separation av oro”. Även användning av servicegränssnitt gör det möjligt för oss att enkelt testa programmet genom att håna MessageService och binda tjänsterna vid körning i stället för att kompilera tid.
nu är vi redo att skriva java-beroendeinjektorklasser som initierar tjänsten och även konsumentklasser.
Java Dependency Injection – Injectors Classes
Låt oss ha ett gränssnittMessageServiceInjector
med metoddeklaration som returnerar klassenConsumer
.,
package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;public interface MessageServiceInjector {public Consumer getConsumer();}
nu för varje tjänst måste vi skapa injektorklasser som nedan.
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());}}
låt oss nu se hur våra klientapplikationer kommer att använda programmet med ett enkelt program.
som du kan se att våra applikationsklasser endast är ansvariga för att använda tjänsten. Serviceklasser skapas i injektorer. Även om vi måste ytterligare utöka vår ansökan för att tillåta facebook messaging, vi kommer att behöva skriva service klasser och injektor klasser endast.,
så implementering av beroendeinjektion löste problemet med hårdkodat beroende och hjälpte oss att göra vår ansökan flexibel och lätt att förlänga. Låt oss nu se hur lätt vi kan testa vår applikationsklass genom att håna injektorn och serviceklasserna.
Java Dependency Injection – JUnit Test Case with Mock Injector and Service
som du kan se att jag använder anonyma klasser för att håna injektorn och serviceklasser och jag kan enkelt testa mina applikationsmetoder., Jag använder JUnit 4 för ovanstående testklass, så se till att det är i din projektbyggnadsväg om du kör över testklassen.
Vi har använt konstruktörer för att injicera beroenden i applikationsklasserna, ett annat sätt är att använda en setter-metod för att injicera beroenden i applikationsklasser. För setter method dependency injection kommer vår applikationsklass att implementeras som nedan.
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;}}
ett av de bästa exemplen på setter dependency injection är Struts2 Servlet API Aware-gränssnitt.,
Om du vill använda Konstruktörsbaserad beroendeinjektion eller setterbaserad är ett designbeslut och beror på dina krav. Till exempel, om min ansökan inte kan fungera alls utan serviceklassen skulle jag föredra konstruktörsbaserad DI eller annars skulle jag gå till setter method based DI för att bara använda den när den verkligen behövs.
Dependency Injection in Java är ett sätt att uppnå Inversion av kontroll (IoC) i vår ansökan genom att flytta objekt bindande från sammanställa tid till runtime., Vi kan uppnå IoC genom Fabriksmönster, Mallmetod designmönster, Strategimönster och Service Locator mönster också.
Vår Dependency Injection, Google Guice och Java EE CDI ramar underlätta processen av dependency injection genom användning av Java Reflection API och java anteckningar. Allt vi behöver är att kommentera fältet, konstruktören eller setter-metoden och konfigurera dem i konfigurations xml-filer eller klasser.,några av fördelarna med att använda Beroendeinjektion i Java är:
- Separation av problem
- Boilerplate Kodreduktion i applikationsklasser eftersom allt arbete för att initiera beroenden hanteras av injektorkomponenten
- konfigurerbara komponenter gör ansökan lätt utdragbar
- enhetstestning är lätt med mock objekt
nackdelar med Java Beroendeinjektion
Java Beroendeinjektions
dependency injection har också vissa nackdelar:
- om överanvändning kan det leda till underhållsproblem eftersom effekten av förändringar är kända vid körning.,
- Dependency injection i java döljer beroenden i serviceklassen som kan leda till runtime-fel som skulle ha fångats vid kompileringstiden.
det är allt för beroendeinjektionsmönster i java. Det är bra att veta och använda den när vi har kontroll över tjänsterna.