Wstrzykiwanie zależności: DI & IoC

Wstrzykiwanie zależności (ang. dependency injection) jest konkretnym przypadkiem metodyki wytwarzania oprogramowania, którą nazywamy potocznie z języka angielskiego - IOC (Inversion of Control). Odwrócenie sterowania polega na przekazaniu kontroli nad cyklem życia obiektów kontenerowi.
Kontener Springa jest odpowiedzialny za tworzenie obiektów (tzw. beanów) oraz dostarczanie ich w odpowiednim momencie do danej klasy. Krótko mówiąc, jeśli do tej pory programista chciał stworzyć instancję obiektu, był on zobowiązany do użycia słowa kluczowego new:
ItemService itemService = new ItemService();
Obecnie, korzystając z kontenera Springa, w ogóle nie musi się on martwić o wykonanie tej operacji, ponieważ Spring zrobi to niejawnie za niego. Jak zatem uzyskać referencję do obiektu tworzonego przez kontener? W bardzo prosty sposób. Obiekt taki możemy wstrzyknąć do naszej klasy poprzez konstruktor, pole (field) lub metodę set (setter). Wiązania tego typu w zdecydowanej większości przypadków oznaczamy adnotacją @Autowired:
  • Konstruktor - w tym przypadku dodajemy adnotację nad konstruktorem i w ten sposób wstrzykujemy obiekt itemService jako parametr (od wersji 4.3 Spring umożliwia w ogóle pominięcie adnotacji @Autowired, jednak tylko w przypadku gdy klasa posiada zdefiniowany tylko jeden konstruktor):
    public class ItemController {
    
        private ItemService itemService; 
    
        @Autowired
        public ItemController(ItemService itemService) {
            this.itemService = itemService;
        }
    }
    
  • Pole - ustawiamy adnotację nad polem, co jest nieco rzadziej używane, ze względu na pewne utrudnienie napotykane podczas tworzenia testów. Ciężko jest bowiem utworzyć obiekt klasy ItemController w przypadku gdy chcemy zainicjować go od razu naszą własną implementacją ItemService, jeśli konstruktor nie zawiera opcji podania takiego parametru (zakładamy również, że w teście z jakiegoś powodu nie możemy zainicjować kontekstu Springa, co uniemożliwia użycie adnotacji @Autowired):
    public class ItemController {
    
        @Autowired
        private ItemService itemService; 
    
        public ItemController(/* bez parametru ItemService */) {
    
        }
        
        ...
    }
    
  • Setter - ustawiamy adnotację nad metodą - przytaczamy dla porządku (chyba kilka razy w życiu spotkaliśmy coś takiego w kodzie realnego projektu i zawsze dało się to zastąpić wstrzykiwaniem przez konstruktor - aplikacja StartAPPa również nie zawiera ani jednego przypadku użycia wstrzykiwania setterem):
    public class ItemController {
    
        private ItemService itemService; 
    
        @Autowired
        public void setItemService(ItemService itemService) {
            this.itemService = itemService;
        }    
    }
    
Uwagi
Na koniec dwie sprawy, które mogą spędzać sen z powiek u rzetelnych czytelników. Pierwsza z nich dotyczy stwierdzenia, że adnotacje dodajemy u góry (nad konstruktorem, nad polem itp). Piszemy tak z przyzwyczajenia, bo to jest bardzo ale to bardzo popularne rozwiązanie. Absolutna większość używanych przez nas formaterów kodu w projektach jest konfigurowana właśnie w ten sposób. Niemniej dla porządku wspomnijmy, że można takie adnotacje również napisać przed polem, tudzież konstruktorem. Co prawda wydłuża to linie i podczas czytania właściwy kod miesza się optycznie z adnotacjami, ale jest to możliwe i działa.
Druga sprawa dotyczy samej adnotacji @Autowired. Czy ona wyczerpuje wszystkie nasze możliwości, w kontekście opisanych sposobów wiązań? Nie do końca. Alternatywnie możemy użyć również dwóch innych adnotacji, np. @Resource lub @Inject. Stosuje się je jednak relatywnie rzadko bowiem raz, że nie pochodza one z samego Springa, a dwa że warto jednak utrzymywać spojność w kodzie w ramach całości projektu i jeśli coś jest wykonalne za pomocą adnotacji @Autowired, to zwykle dokonuje się takiego wyboru.
Rekomendacja
Zalecamy wiązanie obiektów w Springu przez konstruktor z użyciem adnotacji @Autowired lub bez (od Springa 4.3, w przypadku posiadania tylko jednego konstruktora w klasie). Sprzyja to pisaniu testów oraz jest bardziej naturalnym obiektowo rozwiązaniem, poprzez zastosowanie kompozycji obiektów (zawieranie się w sobie obiektów zależnych).

Jest to szczególnie istotne, gdy piszemy testy jednostkowe, w których nie chcemy stawiać kontekstu Springa. Wówczas możemy zainicjalizować obiekty już na etapie uruchamiania konstruktora takiego obiektu (przekazując w parametrach referencje do obiektów powiązanych). Warto pamiętać, że od dłuższego czasu nie musimy sami tworzyć konstruktorów. Wystarczy, że skorzystamy z biblioteki Lombok, która zrobi to za nas, jeśli użyjemy właściwej adnotacji.
Praktyka


W ramach naszych kursów dotyczących Spring Framework, a także w aplikacji webowej w Kurs Aplikacji Web - Mega pakiet, stosujemy adnotację @Autowired do automatycznego wstrzykiwania zależności. W większości sytuacji preferujemy wstrzykiwanie zależności poprzez konstruktor, co jest zgodne z zalecanymi praktykami i zapewnia większą przejrzystość oraz łatwość testowania kodu.
Zdjęcie autora
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
W tej strefie znajdziesz wszystko co niezbędne, aby komfortowo uczyć się Springa. Doskonale opisany kod nie zawiera zbędnych komplikacji, tylko samą esencję w postaci praktycznych przykładów. Tutaj odnajdziesz wszystko co jest istotne w danym temacie. Otrzymujesz pakiet złożony z kilku projektów wraz z obszernym wytłumaczeniem kodu.
Topowe Materiały
Spring IO: The IoC Container
Spring IO: Dependency Injection
Baeldung: Intro to Inversion of Control
Baeldung: Spring Dependency Injection

Udemy: [NEW] Spring Boot 3, Spring 6 & Hibernate for Beginners  —  polskie napisy

Stale się rozwijamy, a więc bądź na bieżąco!
Na ten adres będziemy przesyłać informacje o ważniejszych aktualizacjach, a także o nowych materiałach pojawiających się na stronie.
Polub nas na Facebooku:
Nasi partnerzy: stackshare
Javappa to również profesjonalne usługi programistyczne oparte o technologie JAVA. Jeśli chesz nawiązać z nami kontakt w celu uzyskania doradztwa bądź stworzenia aplikacji webowej powinieneś poznać nasze doświadczenia.
Kliknij O nas .


Pozycjonowanie stron: Grupa TENSE