Dependency Injection) opisuje proces dostarczania komponentowi niezbędnych zależności z wykorzystaniem techniki IoC — można więc powiedzieć, ż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 wprowadzania (wstrzykiwania) zależności do właściwych obiektów wykorzystuje się znane z komponentów JavaBeans metody ustawiające. Więcej informacji na temat komponentów JavaBeans oraz specyfikację tej technologii znajdziesz na stronie internetowej http://java.sun.
Ã¥com/products/javabeans.
D:\! AAA DZISIAJ\Spring Framework. Profesjonalne tworzenie oprogramowania w Javie\9 druk\r02.doc 85
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 — odpowiedniej 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:
public class WeatherServiceTest extends TestCase {
...
}
86
D:\! AAA DZISIAJ\Spring Framework. Profesjonalne tworzenie oprogramowania w Javie\9 druk\r02.doc
Rozdział 2. n 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-leżności w tej formie przenosi na kontener odpowiedzialność za implementowanie metod w czasie wykonywania programu. Przykładowo, obiekt może definiować chronioną metodę abstrakcyjną, a kontener może tę metodę implementować w czasie wykonywania programu w taki sposób, aby zwracała obiekt zlokalizowany podczas przeszukiwania środowiska wykonywania aplikacji. Celem wstrzykiwania metod jest oczywiście wyeliminowanie zależ-
ności od interfejsów API kontenera i tym samym ograniczanie niepożądanych związków.
Jednym z podstawowych i jednocześnie najlepszych zastosowań techniki wstrzykiwania metod jest obsługa przypadków, w których bezstanowy obiekt, singleton, musi współpracować z niesingletonem, z obiektem stanowym lub takim, który nie zapewnia bezpieczeń-
stwa przetwarzania wielowątkowego. Przypomnij sobie naszą usługę pogodową, w której potrzebujemy tylko jednego egzemplarza, ponieważ nasza implementacja jest bezstanowa i jako taka może być wdrażana za pomocą domyślnego kontenera Springa, który traktuje ją jak singleton (tworzy tylko jeden egzemplarz, który można przechowywać w pamięci podręcznej i wykorzystywać wielokrotnie). Warto się jednak zastanowić, co by było, gdyby usługa pogodowa musiała korzystać z klasy StatefulWeatherDao, implementacji interfejsu WeatherDao niezapewniającej bezpieczeństwa wątków. W każdym wywołaniu metody WeatherService.getHistoricalHigh() usługa pogodowa musiałaby wykorzystywać świeży egzemplarz obiektu DAO (lub przynajmniej musiałaby się upewniać, że w danej chwili żaden inny egzemplarz samej usługi nie wykorzystuje tego samego obiektu DAO). Jak się za chwilę przekonasz, można w prosty sposób zasygnalizować kontenerowi konieczność traktowania DAO jak obiektu, który nie jest singletonem — wówczas każde żądanie dotyczące tego obiektu spowoduje zwrócenie nowego egzemplarza. Problem w tym, że pojedynczy egzemplarz usługi pogodowej jest przedmiotem wstrzykiwania zależności tylko raz.