[ Pobierz całość w formacie PDF ]
wewnętrzny nie znajduje żadnych zastosowań poza zakresem komponentu zewnętrznego.
W porównaniu z poprzednią wersją tego przykładu obiekt DAO (który ustawiono jako za-
leżność usługi pogodowej) został włączony do komponentu usługi pogodowej i przyjął po-
stać jego komponentu wewnętrznego. %7ładen inny komponent ani użytkownik zewnętrzny
nie będzie przecież potrzebował tego obiektu DAO, zatem utrzymywanie go poza zakresem
komponentu usługi (jako osobnej, zewnętrznej definicji) mijałoby się z celem. Użycie kompo-
nentu wewnętrznego jest w tym przypadku rozwiązaniem bardziej zwięzłym i klarownym.
Komponent wewnętrzny nie musi mieć zdefiniowanego identyfikatora, choć nie jest to za-
bronione. Uwaga: Komponenty wewnętrzne zawsze są komponentami prototypowymi,
a ewentualny atrybut singleton jest ignorowany. W tym przypadku nie ma to najmniejszego
znaczenia ponieważ istnieje tylko jeden egzemplarz komponentu zewnętrznego (który
jest singletonem), utworzenie więcej niż jednego egzemplarza komponentu wewnętrznego
jest wykluczone (niezależnie od tego, czy zadeklarujemy ten komponent jako singletonowy
czy jako prototypowy). Gdyby jednak prototypowy komponent zewnętrzny potrzebował
zależności singletonowej, nie powinniśmy tej zależności definiować w formie komponentu
wewnętrznego, tylko jako odwołanie do singletonowego komponentu zewnętrznego.
Samodzielne (ręczne) deklarowanie zależności
Kiedy właściwość komponentu lub argument konstruktora odwołuje się do innego komponentu,
mamy do czynienia z deklaracją zależności od tego zewnętrznego komponentu. W niektó-
rych sytuacjach konieczne jest wymuszenie inicjalizacji jednego komponentu przed innym,
nawet jeśli ten drugi nie został zadeklarowany jako właściwość pierwszego. Wymuszanie
określonej kolejności inicjalizacji jest uzasadnione także w innych przypadkach, np. kiedy
Rozdział 2. Fabryka komponentów i kontekst aplikacji 109
dana klasa wykonuje jakieś statyczne operacje inicjalizujące w czasie wczytywania. Przy-
kładowo, sterowniki baz danych zwykle są rejestrowane w egzemplarzu interfejsu Driver-
Manager biblioteki JDBC. Do ręcznego określania zależności pomiędzy komponentami słu-
ży atrybut repenrs-on, który wymusza utworzenie egzemplarza innego komponentu jeszcze
przed uzyskaniem dostępu do komponentu zależnego. Poniższy przykład pokazuje, jak
można wymuszać wczytywanie sterownika bazy danych:
...
Warto pamiętać, że większość pul połączeń z bazą danych oraz klas pomocniczych Springa
(np. DriverManagerDataSource) korzysta z tego mechanizmu wymuszania wczytywania,
zatem powyższy fragment kodu jest tylko przykładem popularnego rozwiązania.
Automatyczne wiązanie zależności
Do tej pory mieliśmy do czynienia z deklaracjami zależności komponentów wyrażanymi
wprost (za pośrednictwem wartości właściwości i argumentów konstruktora). W pewnych
okolicznościach Spring może użyć mechanizmu introspekcji klas komponentów w ramach
bieżącej fabryki i przeprowadzić automatyczne wiązanie zależności. W takim przypadku
właściwość komponentu lub argument kontenera nie muszą być deklarowane (np. w pliku
XML), ponieważ Spring użyje refleksji do odnalezienia typu i nazwy odpowiedniej wła-
ściwości, po czym dopasuje ją do innego komponentu w danej fabryce (według jego typu
lub nazwy). Takie rozwiązanie może co prawda oszczędzić programiście mnóstwo pracy
związanej z samodzielnym przygotowywaniem odpowiedniego kodu, jednak niewątpliwym
kosztem tego podejścia jest mniejsza przejrzystość. Mechanizm automatycznego wiązania
zależności można kontrolować zarówno na poziomie całego kontenera, jak i na poziomie
definicji poszczególnych komponentów. Ponieważ nieostrożne korzystanie z tej techniki
może prowadzić do nieprzewidywalnych rezultatów, mechanizm automatycznego wiązania
jest domyślnie wyłączony. Automatyczne wiązanie na poziomie komponentów jest kon-
trolowane za pośrednictwem atrybutu autowire, który może zawierać pięć wartości:
no mechanizm automatycznego wiązania zależności w ogóle nie będzie
stosowany dla danego komponentu. Właściwości tego komponentu oraz argumenty
konstruktora muszą być deklarowane wprost, a wszelkie odwołania do innych
komponentów wymagają używania elementu ref. Okazuje się, że jest to domyślny
sposób obsługi poszczególnych komponentów (przynajmniej jeśli domyślne
ustawienia na poziomie fabryki komponentów nie zostały zmienione). Opisany tryb
jest zalecany w większości sytuacji, szczególnie w przypadku większych wdrożeń,
gdzie zależności deklarowane wprost stanowią swoistą dokumentację struktury
oprogramowania i są dużo bardziej przejrzyste.
byName wymusza automatyczne wiązanie zależności według nazw właściwości.
Nazwy właściwości są wykorzystywane podczas odnajdywania dopasowań
do komponentów w bieżącej fabryce komponentów. Przykładowo, jeśli dana
właściwość ma przypisaną nazwę weatherDao, wówczas kontener spróbuje ustawić
tę właściwość jako odwołanie do innego komponentu nazwanego właśnie weatherDao.
110 Spring Framework. Profesjonalne tworzenie oprogramowania w Javie
Jeśli taki pasujący komponent nie zostanie znaleziony, właściwość pozostanie
nieustawiona. Taka reakcja na brak dopasowania pomiędzy nazwą właściwości
a nazwą komponentu jest opcjonalna jeśli chcesz traktować brak dopasowania
jak błąd, możesz do definicji komponentu dodać atrybut repenrency-check="objects"
(patrz dalsza część tego rozdziału).
byType automatyczne wiązanie zależności przez dopasowywanie typów. Podobne
rozwiązanie zastosowano w kontenerze PicoContainer, innym popularnym produkcie
obsługującym wstrzykiwanie zależności. W przypadku każdej właściwości jeśli
w bieżącej fabryce komponentów istnieje dokładnie jeden komponent tego samego
typu co ta właściwość wartość jest ustawiana właśnie jako ten komponent. Jeśli
[ Pobierz całość w formacie PDF ]