Java Dependency Injection-DI Design Pattern Example Tutorial (Polski)

Java Dependency Injection design pattern pozwala nam usunąć ciężko zakodowane zależności i sprawić, że nasza aplikacja będzie luźno powiązana, rozszerzalna i utrzymywalna. Możemy zaimplementować dependency injection w Javie, aby przenieść rozwiązywanie zależności z czasu kompilacji do środowiska uruchomieniowego.,

Java Dependency Injection

Java Dependency injection wydaje się trudny do uchwycenia z teorią, więc podałbym prosty przykład i wtedy zobaczymy, jak użyć wzorca dependency injection, aby uzyskać luźne sprzężenie i rozszerzalność w aplikacji.

Załóżmy, że mamy aplikację, w której zużywamyEmailService do wysyłania wiadomości e-mail. Normalnie zaimplementowalibyśmy to jak poniżej.

EmailService Klasa przechowuje logikę wysyłania wiadomości e-mail na adres e-mail odbiorcy., Nasz kod aplikacji będzie jak poniżej.

Nasz kod klienta, który będzie używał klasy MyApplication do wysyłania wiadomości e-mail, będzie taki jak poniżej.

na pierwszy rzut oka wydaje się, że w powyższej implementacji nie ma nic złego. Ale powyżej logika kodu ma pewne ograniczenia.

  • MyApplication klasa jest odpowiedzialna za zainicjowanie usługi e-mail, a następnie jej użycie. Prowadzi to do twardego zakodowania zależności. Jeśli chcemy w przyszłości przełączyć się na jakąś inną zaawansowaną usługę poczty elektronicznej, będzie ona wymagała zmian kodu w klasie aplikacji MyApplication., To sprawia, że nasza aplikacja jest trudna do rozszerzenia, a jeśli usługa e-mail jest używana w wielu klasach, to byłoby jeszcze trudniejsze.
  • jeśli chcemy rozszerzyć naszą aplikację, aby zapewnić dodatkową funkcję przesyłania wiadomości, taką jak SMS lub Facebook message, musimy napisać do tego inną aplikację. Będzie to wiązało się ze zmianami kodu w klasach aplikacji i klasach klientów.
  • testowanie aplikacji będzie bardzo trudne, ponieważ nasza aplikacja bezpośrednio tworzy instancję usługi e-mail. Nie ma mowy, żebyśmy wyśmiewali te obiekty w naszych klasach testowych.,

można argumentować, że możemy usunąć tworzenie instancji usługi e-mail z klasy MyApplication, mając konstruktor, który wymaga usługi e-mail jako argumentu.

ale w tym przypadku prosimy aplikacje klienckie lub klasy testowe o zainicjowanie usługi e-mail, która nie jest dobrą decyzją projektową.

teraz zobaczmy, jak możemy zastosować java dependency injection pattern, aby rozwiązać wszystkie problemy z powyższą implementacją., Wtrysk zależności w Javie wymaga co najmniej następujących elementów:

  1. komponenty usługi powinny być zaprojektowane z klasą bazową lub interfejsem. Lepiej jest preferować interfejsy lub abstrakcyjne klasy, które definiowałyby kontrakt dla usług.
  2. klasy konsumenckie powinny być napisane w interfejsie usługi.
  3. klasy wtryskiwaczy, które zainicjalizują usługi, a następnie klasy konsumenckie.

Java Dependency Injection – Service Components

w naszym przypadku możemy mieć MessageService, który zadeklaruje umowę na implementacje usług.,

package com.journaldev.java.dependencyinjection.service;public interface MessageService {void sendMessage(String msg, String rec);}

Załóżmy teraz, że mamy usługi e-mail i SMS, które implementują powyższe interfejsy.

nasze usługi Java injection są gotowe i teraz możemy napisać naszą klasę konsumencką.

Java Dependency Injection – Service Consumer

nie musimy mieć interfejsów bazowych dla klas konsumenckich, ale będę miałConsumer interfejs deklarujący umowę dla klas konsumenckich.

package com.journaldev.java.dependencyinjection.consumer;public interface Consumer {void processMessages(String msg, String rec);}

moja Implementacja klasy konsumenckiej jest jak poniżej.

zauważ, że nasza klasa aplikacji właśnie korzysta z usługi., Nie inicjuje usługi, która prowadzi do lepszego „rozdzielenia obaw”. Również wykorzystanie interfejsu serwisowego pozwala nam na łatwe testowanie aplikacji poprzez wyśmiewanie MessageService i Wiązanie usług w czasie wykonywania, a nie w czasie kompilacji.

teraz jesteśmy gotowi napisać klasy Java dependency injector, które zainicjalizują usługę, a także klasy consumer.

Java Dependency Injection – klasy wtryskiwaczy

Let ' s have an interfaceMessageServiceInjector with method declaration that returns theConsumer class.,

package com.journaldev.java.dependencyinjection.injector;import com.journaldev.java.dependencyinjection.consumer.Consumer;public interface MessageServiceInjector {public Consumer getConsumer();}

teraz dla każdej usługi będziemy musieli utworzyć klasy wtryskiwaczy jak poniżej.

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());}}

teraz zobaczmy, jak nasze aplikacje klienckie będą używać aplikacji z prostym programem.

jak widać nasze klasy aplikacji są odpowiedzialne tylko za korzystanie z usługi. Klasy serwisowe są tworzone w wtryskiwaczach. Również jeśli będziemy musieli dalej rozszerzać naszą aplikację, aby umożliwić facebook messaging, będziemy musieli pisać tylko klasy usług i klasy wtryskiwaczy.,

implementacja dependency injection rozwiązała problem z hard-coded dependency i pomogła nam uczynić naszą aplikację elastyczną i łatwą do rozszerzenia. Teraz zobaczmy, jak łatwo możemy przetestować naszą klasę aplikacji, wyśmiewając klasy wtryskiwaczy i usług.

Java Dependency Injection – przypadek testowy JUnit z Mock Injector i Service

Jak widać używam anonimowych klas do mock Injector i service i mogę łatwo przetestować moje metody aplikacji., Używam JUnit 4 dla powyższej klasy testowej, więc upewnij się, że jest w ścieżce budowania projektu, jeśli używasz powyżej klasy testowej.

użyliśmy konstruktorów do wprowadzania zależności w klasach aplikacji, Innym sposobem jest użycie metody setter do wprowadzania zależności w klasach aplikacji. Dla metody setter dependency injection Nasza klasa aplikacji zostanie zaimplementowana jak poniżej.

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;}}

jednym z najlepszych przykładów wtrysku zależności settera są Interfejsy świadome API serwletów Struts2.,

To, czy użyć Constructor based dependency injection lub setter based, jest decyzją projektową i zależy od twoich wymagań. Na przykład, jeśli moja aplikacja nie może w ogóle działać bez klasy service, to wolałbym di oparte na constructor lub wybrałbym DI oparte na metodzie setter, aby używać go tylko wtedy, gdy jest naprawdę potrzebny.

Dependency Injection w Javie jest sposobem na uzyskanie inwersji sterowania (IoC) w naszej aplikacji poprzez przeniesienie wiązania obiektów z czasu kompilacji do czasu runtime., Możemy osiągnąć IoC poprzez wzorzec fabryczny, wzorzec projektowania metody szablonowej, wzorzec strategii i wzorzec lokalizatora usług.

Spring Dependency Injection, Google Guice i Java EE CDI Framework ułatwiają proces wstrzykiwania zależności poprzez wykorzystanie Java Reflection API i Java adnotations. Wystarczy dodać adnotację pola, konstruktora lub metody settera i skonfigurować je w plikach konfiguracyjnych xml lub klasach.,

niektóre z zalet używania iniekcji zależności w Javie to:

  • rozdzielenie obaw
  • redukcja kodu w klasach aplikacji, ponieważ cała praca nad inicjalizacją zależności jest obsługiwana przez komponent wtryskiwacza
  • konfigurowalne komponenty sprawiają, że aplikacja jest łatwo rozszerzalna
  • testowanie jednostkowe jest łatwe z przykładowymi obiektami

wady iniekcji zależności Javy

niektóre wady:

  • jeśli nadużywane, może to prowadzić do problemów z konserwacją, ponieważ efekt zmian jest znany w czasie wykonywania.,
  • dependency injection in java ukrywa zależności klas usług, które mogą prowadzić do błędów uruchomieniowych, które zostałyby przechwycone podczas kompilacji.

to wszystko dla wzorca iniekcji zależności w Javie. Dobrze jest wiedzieć i z niego korzystać, gdy mamy kontrolę nad usługami.

Leave a Comment