[ Pobierz całość w formacie PDF ]
stałe w kodzie zródłowym programu.
Spójrzmy teraz na prosty przykład tego, jak kontener Springa może obsługiwać mechanizm
odwracania kontroli. W pierwszej kolejności przebudujemy naszą usługę pogodową, aby
prezentowała właściwy podział na interfejs i implementację oraz umożliwiała definiowanie
(konfigurowanie) dla tej implementacji konkretnego egzemplarza obiektu DAO w formie
właściwości komponentu JavaBean:
public interface WeatherService {
Double getHistoricalHigh(Date date);
}
public class WeatherServiceImpl implements WeatherService {
private WeatherDao weatherDao;
public void setWeatherDao(WeatherDao weatherDao) {
this.weatherDao = weatherDao;
}
public Double getHistoricalHigh(Date date) {
WeatherData wd = weatherDao.find(date);
if (wd != null)
return new Double(wd.getHigh());
return null;
}
}
// ta sama klasa co w poprzednim przykładzie
public class StaticDataWeatherDaoImpl implements WeatherDao {
...
}
Do zarządzania egzemplarzem usługi pogodowej użyjemy kontekstu aplikacji Springa, a kon-
kretnie klasy ClassPathXmlApplicationContext, i upewnimy się, że kontekst aplikacji otrzymał
obiekt DAO naszej usługi, z którym będzie mógł współpracować. W pierwszej kolejności
musimy zdefiniować plik konfiguracyjny w formacie XML, applicationContext.xml:
"http://www.springframework.org/dtd/spring-beans.dtd"
Rozdział 2. Fabryka komponentów i kontekst aplikacji 85
Obiekt weatherService konfigurujemy za pomocą elementu bean, w którym określamy, że
jego właściwość, weatherDao, powinna być ustawiona na egzemplarz komponentu weatherDao
(który także definiujemy jako element bean). Pozostaje nam już tylko zmodyfikowanie klasy
testowej, aby tworzyła odpowiedni kontener i uzyskiwała dostęp do znajdującej się w tym
kontenerze usługi pogodowej:
public class WeatherServiceTest extends TestCase {
public void testSample2() throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext(
"ch02/sample2/applicationContext.xml");
WeatherService ws = (WeatherService)ctx.getBean("weatherService");
Double high = ws.getHistoricalHigh(new GregorianCalendar(2004, 0, 1).getTime());
// & w tym miejscu powinieneś umieścić dodatkowy kod sprawdzający zwracaną wartość&
}
}
Wszystkie analizowane klasy zostały już zakodowane i wdrożone zgodnie z zaleceniami
IoC. Usługa pogodowa nie ma i nie potrzebuje żadnej wiedzy o szczegółach implementacji
wykorzystywanego obiektu DAO, ponieważ zależność pomiędzy tymi składnikami aplikacji
bazuje wyłącznie na interfejsie WeatherDao. Co więcej, podział oryginalnej klasy Weather-
Service na interfejs WeatherService i implementującą go klasę WeatherServiceImpl chro-
ni klientów usługi pogodowej przed takimi szczegółami implementacyjnymi jak sposób loka-
lizowania przez tę usługę odpowiedniego obiektu DAO (w tym konkretnym przypadku wy-
korzystano metodę ustawiającą znaną z komponentów JavaBeans). Takie rozwiązanie powoduje,
że teraz implementacja usługi pogodowej może być zmieniana w sposób przezroczysty.
Okazuje się, że na tym etapie możemy wymieniać implementacje interfejsu WeatherDao
i (lub) interfejsu WeatherService, i że tego rodzaju zmiany będą wymagały wyłącznie od-
powiedniego dostosowania zapisów pliku konfiguracyjnego (bez najmniejszego wpływu na
funkcjonowanie klientów zmienianych komponentów). Przedstawiony przykład dobrze ilu-
struje zastosowanie interfejsów w sytuacji, gdy kod jednej z warstw wykorzystuje kod innej
warstwy (wspominano o tym w rozdziale 1.).
Różne formy wstrzykiwania zależności
Termin wstrzykiwanie zależności (ang. Dependency Injection) opisuje proces dostarczania
komponentowi niezbędnych zależności z wykorzystaniem techniki IoC można więc po-
wiedzieć, że zależności są w istocie wstrzykiwane do komponentów. Wersja wstrzykiwania
zależności, którą mieliśmy okazję analizować w poprzednim przykładzie, jest nazywana
wstrzykiwaniem przez metody ustawiające (ang. Setter Injection), ponieważ do wprowa-
dzania (wstrzykiwania) zależności do właściwych obiektów wykorzystuje się znane z kom-
ponentów JavaBeans metody ustawiające. Więcej informacji na temat komponentów Java-
Beans oraz specyfikację tej technologii znajdziesz na stronie internetowej http://java.sun.
com/products/javabeans.
86 Spring Framework. Profesjonalne tworzenie oprogramowania w Javie
Przeanalizujmy teraz nieco inny wariant wstrzykiwania zależności wstrzykiwanie przez
konstruktor (ang. Constructor Injection), gdzie zależności są dostarczane do obiektu za
pośrednictwem jego własnego konstruktora:
public interface WeatherService {
Double getHistoricalHigh(Date date);
}
public class WeatherServiceImpl implements WeatherService {
private final WeatherDao weatherDao;
public WeatherServiceImpl(WeatherDao weatherDao) {
this.weatherDao = weatherDao;
}
public Double getHistoricalHigh(Date date) {
WeatherData wd = weatherDao.find(date);
if (wd != null)
return new Double(wd.getHigh());
return null;
}
}
// niezmieniony interfejs WeatherDao
public interface WeatherDao {
...
}
// niezmieniona klasa StaticDataWeatherDaoImpl
public class StaticDataWeatherDaoImpl implements WeatherDao {
...
}
Klasa WeatherServiceImpl zawiera teraz konstruktor, który pobiera w formie argumentu
egzemplarz interfejsu WeatherDao (zamiast jak w poprzednim przykładzie odpowied-
niej metody ustawiającej, która także pobierała na wejściu egzemplarz tego interfejsu).
Oczywiście także konfiguracja kontekstu aplikacji wymaga odpowiedniej modyfikacji.
Okazuje się jednak, że zmiany w żaden sposób nie dotyczą klasy testowej, która nie wymaga
żadnych dodatkowych czynności:
// niezmieniona klasa WeatherServiceTest
public class WeatherServiceTest extends TestCase {
...
}
Rozdział 2. Fabryka komponentów i kontekst aplikacji 87
Wstrzykiwanie metod jest ostatnią formą wstrzykiwania zależności, którą się zajmiemy
(jest stosowana zdecydowanie rzadziej od dwóch poprzednich technik). Wstrzykiwanie za-
[ Pobierz całość w formacie PDF ]