[ Pobierz całość w formacie PDF ]
szość praktycznych usług, kontrolerów i zasobów konfigurowanych w ramach kontenera
i tak jest implementowana w formie klas gwarantujących bezpieczną pracę w środowisku
wielowÄ…tkowym, zatem nie modyfikujÄ… swojego stanu po wykonaniu fazy inicjalizacji.
Niesingletonowe, prototypowe komponenty, jak sama nazwa wskazuje, powinny być defi-
niowane z atrybutem singleton równym false. Warto pamiętać, że cykl życia komponentu
prototypowego często różni się od cyklu życia komponentu singletonowego. Kiedy konte-
ner otrzymuje żądanie dostarczenia komponentu prototypowego, następuje oczywiście ini-
cjalizacja i przekazanie odpowiedniego egzemplarza, ale na tym rola kontenera się kończy
(od tego momentu kontener nie przechowuje zwróconego egzemplarza). O ile więc istnieje
możliwość wymuszenia na kontenerze Springa wykonania pewnych operacji kończących
cykl życia komponentów singletonowych (patrz dalsza część tego rozdziału), w przypadku
komponentów prototypowych te same operacje będzie trzeba zrealizować w kodzie użyt-
kownika, ponieważ kontener nie będzie już miał żadnej wiedzy o zwróconych egzemplarzach
tych komponentów:
102 Spring Framework. Profesjonalne tworzenie oprogramowania w Javie
Definiowanie zależności komponentów
Spełnianie zależności komponentów (czy to w formie innych komponentów, czy tylko pro-
stych wartości potrzebnych do działania danego komponentu) jest prawdziwym jądrem,
kluczowym elementem funkcjonalności kontenera, warto więc dobrze zrozumieć rzeczywiste
działanie tego procesu. Miałeś już okazję zapoznać się z przykładami podstawowych typów
wstrzykiwania zależności, wstrzykiwaniem przez konstruktory i wstrzykiwaniem przez
metody ustawiające, wiesz też, że Spring obsługuje obie formy tej techniki. Przekonałeś
się również, jak Spring może wykorzystać odpowiednią metodę fabrykującą zamiast
używać konstruktora do uzyskiwania początkowego egzemplarza obiektu. Właśnie z uwagi
na konieczność dostarczenia zależności do komponentu stosowanie metody fabrykującej do
uzyskiwania egzemplarza komponentu można de facto uznać za odpowiednik tworzenia
egzemplarza za pośrednictwem konstruktora. W przypadku użycia konstruktora to kontener
odpowiada za zapewnienie wartości (opcjonalnych) argumentów konstruktora (które repre-
zentują zależności). Podobnie, w przypadku metody fabrykującej kontener dostarcza warto-
ści (opcjonalnych) argumentów do metody fabrykującej (także reprezentujące zależności).
Niezależnie od tego, czy początkowy egzemplarz obiektu jest tworzony przez konstruktor czy
przez metodÄ™ fabrykujÄ…cÄ…, od tego momentu wszystkie egzemplarze sÄ… traktowane jednakowo.
Techniki wstrzykiwania przez konstruktory i wstrzykiwania przez metody ustawiajÄ…ce nie
wykluczają się wzajemnie. Nawet jeśli Spring uzyskuje początkowy egzemplarz kompo-
nentu za pośrednictwem konstruktora lub metody fabrykującej i dostarcza wartości argu-
mentów do konstruktora lub metody fabrykującej (wstrzykuje zależności), nadal może sto-
sować mechanizm wstrzykiwania przez metody ustawiające do wprowadzania kolejnych
zależności. Takie rozwiązanie może być szczególnie przydatne np. wtedy, gdy będziemy
musieli użyć i zainicjalizować istniejącą klasę, która z jednej strony zawiera konstruktor
pobierający jeden lub wiele argumentów i generujący komponent w znanym (prawidłowym)
stanie poczÄ…tkowym, ale z drugiej strony bazuje na metodach ustawiajÄ…cych JavaBeans dla
części opcjonalnych właściwości. Gdyby nie obsługa obu form wstrzykiwania zależności,
nie byłbyś w stanie prawidłowo inicjalizować tego rodzaju obiektów w sytuacji, gdyby któraś
z nich wymagała ustawienia opcjonalnych właściwości.
Przeanalizujmy teraz sposób, w jaki kontener inicjalizuje i realizuje zależności komponentów:
Kontener w pierwszej kolejności inicjalizuje definicję komponentu bez tworzenia
jego egzemplarza zwykle następuje to w czasie uruchamiania samego kontenera.
Zależności komponentu mogą być wyrażane wprost, w formie argumentów
konstruktora lub metody fabrykującej i (lub) właściwości komponentu.
Każda właściwość lub argument konstruktora w definicji komponentu ma albo postać
wartości wymagającej ustawienia, albo odwołania do innego komponentu w ramach
danej fabryki komponentów lub nadrzędnej fabryki komponentów.
Rozdział 2. Fabryka komponentów i kontekst aplikacji 103
Kontener wykona tyle operacji sprawdzających poprawność definiowanych zależności,
ile będzie mógł w czasie inicjalizacji definicji komponentu. Jeśli korzystasz
z formatu konfiguracji XML, w przypadku niezgodności konfiguracji z typem XML
DTD w pierwszej kolejności otrzymamy wyjątek wygenerowany przez parser
XML. Nawet jeśli konfiguracja w formacie XML jest poprawna z punktu widzenia
definicji typów DTD, w razie wykrycia logicznej niespójności przez Springa także
otrzymamy odpowiedni wyjątek przykładowo, dwie właściwości mogą się wzajemnie
wykluczać, czego nie da się wykazać wyłącznie na podstawie analizy typów DTD.
Jeśli zależność komponentu nie może być zrealizowana w praktyce (jeśli zależność
komponentu ma postać innego komponentu, który nie istnieje) lub jeśli argument
konstruktora lub wartość właściwości nie może zostać prawidłowo ustawiona,
otrzymamy komunikat o błędzie tylko wtedy, gdy dany kontener rzeczywiście
będzie musiał uzyskać nowy egzemplarz tego komponentu i wstrzyknąć jego
zależności. Jeśli okaże się, że egzemplarz komponentu nigdy nie będzie potrzebny,
nie można wykluczyć, że ewentualne błędy w definicji zależności komponentu lub
samego komponentu nigdy nie zostanÄ… wykryte (przynajmniej do momentu jego
użycia). Między innymi po to, aby umożliwić możliwie szybkie wykrywanie błędów,
konteksty aplikacji (ale nie fabryki komponentów) domyślnie tworzą wstępne
egzemplarze komponentów singletonowych. Faza wstępnego tworzenia egzemplarzy
obejmuje iteracyjne przeszukiwanie wszystkich komponentów singletonowych
(w ich domyślnych stanach), utworzenie egzemplarzy każdej ze wstrzykiwanych
zależności i umieszczenie tych egzemplarzy w pamięci podręcznej. Warto pamiętać,
że etap wstępnego tworzenia egzemplarzy komponentów można zmodyfikować
[ Pobierz całość w formacie PDF ]