Spis treci Przedmowa .............................................................................................................................................. 11 Podzikowania ......................................................................................................................................... 13 O ksice .................................................................................................................................................. 15
CZ 1. PODSTAWY FRAMEWORKA SPRING Rozdzia 1. Zrywamy si do dziaania 1.1.
1.2.
1.3.
1.4.
1.5.
21 Upraszczamy programowanie w Javie . ..................................................................................... 22 1.1.1. Uwalniamy moc zawart w POJO . .............................................................................. 23 1.1.2. Wstrzykujemy zalenoci . ............................................................................................ 25 1.1.3. Stosujemy aspekty . ....................................................................................................... 29 1.1.4. Ograniczamy stosowanie kodu szablonowego dziki wzorcom . ................................ 33 Kontener dla naszych komponentów . ....................................................................................... 36 1.2.1. Pracujemy z kontekstem aplikacji . .............................................................................. 37 1.2.2. Cykl ycia komponentu . ............................................................................................... 37 Podziwiamy krajobraz Springa . ................................................................................................. 39 1.3.1. Moduy Springa . ........................................................................................................... 39 1.3.2. Rodzina projektów wokó Springa . ............................................................................. 42 Co nowego w Springu . ................................................................................................................ 46 1.4.1. Co nowego w Springu 2.5? . ......................................................................................... 46 1.4.2. Co nowego w Springu 3.0? . ......................................................................................... 47 1.4.3. Co nowego w rodzinie projektów otaczajcych Springa? . ......................................... 47 Podsumowanie ............................................................................................................................. 48
Rozdzia 2. Tworzymy powizania midzy komponentami 2.1.
2.2.
2.3.
2.4.
49
Deklarujemy komponenty . ......................................................................................................... 50 2.1.1. Tworzymy konfiguracj Springa . ................................................................................ 51 2.1.2. Deklarujemy prosty komponent . ................................................................................. 51 2.1.3. Wstrzykujemy przez konstruktory . ............................................................................. 53 2.1.4. Ustalamy zakres komponentów . .................................................................................. 58 2.1.5. Inicjalizujemy i likwidujemy komponenty . ................................................................ 59 Wstrzykujemy wartoci do waciwoci komponentu . ............................................................ 61 2.2.1. Wstrzykujemy proste wartoci . ................................................................................... 62 2.2.2. Wstrzykujemy referencje do innych beanów . ............................................................ 63 2.2.3. Wiemy waciwoci w przestrzeni nazw p Springa . ............................................... 66 2.2.4. Wiemy kolekcje . ....................................................................................................... 67 2.2.5. Wiemy nic (null) . ...................................................................................................... 72 Wi emy za pomoc wyra e . ................................................................................................... 72 2.3.1. Podstawy wyrae w SpEL . ........................................................................................ 73 2.3.2. Wykonujemy operacje na wartociach w jzyku SpEL . ............................................ 76 2.3.3. Przesiewamy kolekcje za pomoc SpEL . .................................................................... 80 Podsumowanie ............................................................................................................................. 83
6
Spis treci
Rozdzia 3. Ograniczamy u ycie jzyka XML w konfiguracji Springa 3.1.
3.2.
3.3.
3.4.
3.5.
Automatycznie wi emy waciwoci komponentów . .............................................................. 86 3.1.1. Cztery rodzaje automatycznego wizania . .................................................................. 86 3.1.2. Domylny styl automatycznego wizania . .................................................................. 90 3.1.3. Mieszamy wizanie automatyczne i jawne . ................................................................ 91 Wi emy za pomoc adnotacji . ................................................................................................. 92 3.2.1. Korzystamy z adnotacji @Autowired . ......................................................................... 92 3.2.2. Stosujemy automatyczne wizanie zgodne ze standardami, korzystajc z adnotacji @Inject . .................................................................................. 97 3.2.3. Posugujemy si wyraeniami podczas wstrzykiwania przez adnotacje . .................. 99 Automatyczne wykrywanie komponentów . ............................................................................ 100 3.3.1. Oznaczamy komponenty adnotacjami dla automatycznego wykrywania . ............... 100 3.3.2. Dodajemy filtry do skanera komponentów . .............................................................. 102 U ywamy w Springu konfiguracji opartej na Javie . .............................................................. 103 3.4.1. Przygotowujemy si do stosowania konfiguracji opartej na Javie . .......................... 103 3.4.2. Definiujemy klas konfiguracyjn . ............................................................................ 104 3.4.3. Deklarujemy prosty komponent . ............................................................................... 104 3.4.4. Wstrzykujemy w Springu za pomoc konfiguracji opartej na Javie . ....................... 105 Podsumowanie ........................................................................................................................... 106
Rozdzia 4. Aspektowy Spring 4.1.
4.2.
4.3.
4.4.
4.5. 4.6.
85
107
Czym jest programowanie aspektowe . .................................................................................... 108 4.1.1. Definiujemy terminologi dotyczc AOP . .............................................................. 109 4.1.2. Obsuga programowania aspektowego w Springu . .................................................. 112 Wybieramy punkty zczenia za pomoc punktów przecicia . ............................................ 115 4.2.1. Piszemy definicje punktów przecicia . ..................................................................... 116 4.2.2. Korzystamy z desygnatora bean() w Springu . ........................................................... 117 Deklarujemy aspekty w jzyku XML . ..................................................................................... 117 4.3.1. Deklarujemy porady before i after . ........................................................................... 119 4.3.2. Deklarujemy porad around . ..................................................................................... 121 4.3.3. Przekazujemy parametry do porady . ......................................................................... 123 4.3.4. Wprowadzamy now funkcjonalno przez aspekty . ............................................... 125 U ywamy adnotacji dla aspektów . ........................................................................................... 127 4.4.1. Tworzymy porad around za pomoc adnotacji . ...................................................... 129 4.4.2. Przekazujemy argumenty do porad konfigurowanych przez adnotacje . ................. 130 4.4.3. Tworzymy wprowadzenie za pomoc adnotacji . ...................................................... 131 Wstrzykujemy aspekty z AspectJ . ............................................................................................ 132 Podsumowanie ........................................................................................................................... 135
CZ 2. PODSTAWY APLIKACJI SPRINGA Rozdzia 5. Korzystanie z bazy danych
139
5.1.
Filozofia dostpu do danych Springa . ..................................................................................... 140 5.1.1. Hierarchia wyjtków zwizanych z dostpem do danych w Springu . .................... 141 5.1.2. Szablony dostpu do danych . .................................................................................... 143 5.1.3. Klasy bazowe DAO . ................................................................................................... 145 Konfiguracja róda danych . .................................................................................................... 147 5.2.1.
róda danych JNDI .................................................................................................. 147 5.2.2.
róda danych z pul . ................................................................................................. 147 5.2.3.
ródo danych oparte na sterowniku JDBC . ............................................................ 149
5.2.
Spis treci 5.3.
5.4.
5.5.
5.6.
U ywanie JDBC w Springu . ..................................................................................................... 149 5.3.1. Kod JDBC a obsuga wyjtków . ................................................................................ 150 5.3.2. Praca z szablonami JDBC . ......................................................................................... 153 Integracja Hibernate ze Springiem . ....................................................................................... 158 5.4.1. Przegld Hibernate . ................................................................................................... 159 5.4.2. Deklarowanie fabryki sesji Hibernate . ..................................................................... 160 5.4.3. Hibernate bez Springa . .............................................................................................. 162 Spring i Java Persistence API . ................................................................................................. 163 5.5.1. Konfiguracja fabryki menederów encji . .................................................................. 164 5.5.2. Klasa DAO na bazie JPA . ........................................................................................... 168 Podsumowanie ........................................................................................................................... 169
Rozdzia 6. Zarzdzanie transakcjami 6.1.
6.2.
6.3. 6.4.
6.5.
7.2.
7.3.
7.4.
7.5.
7.6.
171
Zrozumienie transakcji . ............................................................................................................ 172 6.1.1. Cztery sowa kluczowe do zrozumienia transakcji . .................................................. 173 6.1.2. Zrozumienie obsugi zarzdzania transakcjami w Springu . ..................................... 174 Wybór mened era transakcji . .................................................................................................. 175 6.2.1. Transakcje JDBC . ...................................................................................................... 175 6.2.2. Transakcje Hibernate . ................................................................................................ 176 6.2.3. Transakcje Java Persistence API . .............................................................................. 177 6.2.4. Transakcje Java Transaction API . .............................................................................. 178 Programowanie transakcji w Springu . .................................................................................... 178 Deklarowanie transakcji . ......................................................................................................... 180 6.4.1. Definiowanie atrybutów transakcji . .......................................................................... 180 6.4.2. Deklarowanie transakcji w XML . .............................................................................. 184 6.4.3. Definiowanie transakcji sterowanych adnotacjami . ................................................. 186 Podsumowanie ........................................................................................................................... 187
Rozdzia 7. Budowanie aplikacji sieciowych za pomoc Spring MVC 7.1.
7
189
Wprowadzenie do Spring MVC . ............................................................................................. 190 7.1.1. Cykl ycia dania w Spring MVC . ........................................................................... 190 7.1.2. Konfiguracja Spring MVC . ........................................................................................ 192 Budowa podstawowego kontrolera . ........................................................................................ 193 7.2.1. Konfiguracja Spring MVC sterowanego adnotacjami . ............................................. 194 7.2.2. Definiowanie kontrolera strony gównej . ................................................................. 195 7.2.3. Produkowanie widoków . ............................................................................................ 198 7.2.4. Definiowanie widoku strony gównej . ...................................................................... 202 7.2.5. Dopracowanie kontekstu aplikacji Springa . ............................................................. 203 Kontroler obsugujcy dane wprowadzane przez u ytkownika . .......................................... 205 7.3.1. Budowa kontrolera przetwarzajcego dane wprowadzane przez uytkownika . ..... 205 7.3.2. Wywietlenie widoku . ................................................................................................ 207 Przetwarzanie formularzy . ....................................................................................................... 208 7.4.1. Wywietlenie formularza rejestracyjnego . ................................................................ 209 7.4.2. Przetwarzanie formularza . ......................................................................................... 211 7.4.3. Walidacja przesyanych danych . ............................................................................... 213 Obsuga plików wysyanych na serwer . .................................................................................. 217 7.5.1. Dodanie pola selektora plików do formularza . ......................................................... 217 7.5.2. Odbieranie plików wysyanych na serwer . ............................................................... 218 7.5.3. Konfiguracja Springa do przesyania plików na serwer . .......................................... 221 Podsumowanie ........................................................................................................................... 221
8
Spis treci
Rozdzia 8. Praca ze Spring Web Flow 8.1. 8.2.
8.3.
8.4. 8.5.
Instalacja Spring Web Flow . ................................................................................................... 224 8.1.1. Konfiguracja Spring Web Flow . ................................................................................ 224 Skadowe przepywu . ................................................................................................................ 227 8.2.1. Stany ........................................................................................................................... 227 8.2.2. Przejcia . ..................................................................................................................... 230 8.2.3. Dane przepywu . ........................................................................................................ 231 czymy wszystko w cao : zamówienie pizzy . .................................................................... 233 8.3.1. Definiowanie bazowego przepywu . ......................................................................... 233 8.3.2. Zbieranie informacji o kliencie . ................................................................................. 237 8.3.3. Budowa zamówienia . ................................................................................................. 242 8.3.4. Przyjmowanie patnoci . ............................................................................................ 245 Zabezpieczanie przepywu . ...................................................................................................... 247 Podsumowanie ........................................................................................................................... 247
Rozdzia 9. Zabezpieczanie Springa 9.1.
9.2.
9.3.
9.4.
9.5.
9.6.
223
249
Wprowadzenie do Spring Security . ........................................................................................ 250 9.1.1. Rozpoczynamy prac ze Spring Security . ................................................................. 250 9.1.2. Konfiguracyjna przestrze nazw Spring Security . ................................................... 251 Zabezpieczanie da sieciowych . .......................................................................................... 252 9.2.1. Poredniczenie w dostpie do filtrów serwletów . .................................................... 252 9.2.2. Minimalna konfiguracja bezpieczestwa sieciowego . .............................................. 253 9.2.3. Przechwytywanie da . ............................................................................................ 257 Zabezpieczanie elementów na poziomie widoku . .................................................................. 259 9.3.1. Dostp do informacji uwierzytelniajcych . .............................................................. 260 9.3.2. Wywietlanie z uprawnieniami . ................................................................................ 261 Uwierzytelnianie u ytkowników . ............................................................................................. 263 9.4.1. Konfiguracja repozytorium w pamici operacyjnej . ................................................ 263 9.4.2. Uwierzytelnianie za pomoc bazy danych . ............................................................... 264 9.4.3. Uwierzytelnianie za pomoc LDAP . ......................................................................... 266 9.4.4. Wczenie funkcji „pamitaj mnie” . .......................................................................... 269 Zabezpieczanie metod . ............................................................................................................. 270 9.5.1. Zabezpieczanie metod z adnotacj @Secured . ........................................................ 270 9.5.2. Adnotacja @RolesAllowed ze specyfikacji JSR-250 . ............................................... 271 9.5.3. Zabezpieczenia przed wykonaniem metody ze SpEL i po jej wykonaniu . ............ 271 9.5.4. Deklaracja przeci bezpieczestwa na poziomie metody . ..................................... 276 Podsumowanie ........................................................................................................................... 276
CZ 3. INTEGRACJA W SPRINGU Rozdzia 10. Praca ze zdalnymi usugami 279 10.1. Zdalny dostp w Springu . ......................................................................................................... 280 10.2. Praca z RMI ............................................................................................................................... 282 10.2.1. Eksportowanie usugi RMI . ...................................................................................... 283 10.2.2. Dowizanie usugi RMI . ............................................................................................ 285 10.3. Udostpnianie zdalnych usug za pomoc Hessian i Burlap . ............................................... 287 10.3.1. Udostpnianie funkcjonalnoci komponentu za pomoc Hessian/Burlap . ............. 288 10.3.2. Dostp do usug Hessian/Burlap . .............................................................................. 290
Spis treci
9
10.4. Obiekt HttpInvoker . ................................................................................................................. 292 10.4.1. Udostpnianie komponentów jako usug HTTP . ..................................................... 292 10.4.2. Dostp do usug przez HTTP . ................................................................................... 293 10.5. Publikacja i konsumpcja usug sieciowych . ............................................................................ 294 10.5.1. Tworzenie punktów kocowych JAX-WS w Springu . ............................................. 295 10.5.2. Porednik usug JAX-WS po stronie klienta . ............................................................ 299 10.6. Podsumowanie ........................................................................................................................... 300
Rozdzia 11. Spring i model REST
301
11.1. Zrozumienie REST . .................................................................................................................. 302 11.1.1. Fundamenty REST . ................................................................................................... 302 11.1.2. Obsuga REST w Springu . ........................................................................................ 303 11.2. Tworzenie kontrolerów korzystajcych z zasobów . ............................................................... 303 11.2.1. Kontroler niezgodny z konwencj REST pod lup . ................................................. 304 11.2.2. Obsuga adresów URL typu RESTful . ...................................................................... 305 11.2.3. Czasowniki REST . ..................................................................................................... 308 11.3. Reprezentacja zasobów . ........................................................................................................... 311 11.3.1. Negocjowanie reprezentacji zasobu . ......................................................................... 311 11.3.2. Praca z konwerterami komunikatów HTTP . ............................................................ 314 11.4. Tworzenie klientów REST . ...................................................................................................... 317 11.4.1. Operacje szablonu RestTemplate . ............................................................................. 319 11.4.2. Pobieranie zasobów za pomoc GET . ....................................................................... 320 11.4.3. Umieszczanie zasobów na serwerze za pomoc PUT . ............................................. 322 11.4.4. Usuwanie zasobów za pomoc DELETE . ................................................................ 324 11.4.5. Wysyanie danych zasobu za pomoc POST . ........................................................... 325 11.4.6. Wymiana zasobów . ..................................................................................................... 327 11.5. Wysyanie formularzy typu RESTful . ..................................................................................... 329 11.5.1. Umieszczanie ukrytych pól metod w kodzie za pomoc JSP . ................................. 330 11.5.2. Demaskowanie rzeczywistego dania . .................................................................... 330 11.6. Podsumowanie ........................................................................................................................... 332
Rozdzia 12. Obsuga komunikatów w Springu
333
12.1. Krótki wstp do JMS . ................................................................................................................ 334 12.1.1. Architektura JMS . ...................................................................................................... 335 12.1.2. Szacowanie korzyci zwizanych z uyciem JMS . ................................................... 337 12.2. Konfiguracja brokera komunikatów w Springu . ................................................................... 338 12.2.1. Tworzenie fabryki pocze . ...................................................................................... 339 12.2.2. Deklaracja miejsca docelowego komunikatów ActiveMQ . ...................................... 340 12.3. Szablon JMS Springa . ............................................................................................................... 340 12.3.1. Kod JMS a obsuga wyjtków . ................................................................................... 341 12.3.2. Praca z szablonami JMS . ............................................................................................ 342 12.4. Tworzenie obiektów POJO sterowanych komunikatami . ..................................................... 347 12.4.1. Tworzenie odbiorcy komunikatów . ........................................................................... 348 12.4.2. Konfiguracja odbiorców komunikatów . .................................................................... 349 12.5. U ywanie RPC opartego na komunikatach . ........................................................................... 350 12.5.1. Praca z RPC opartym na komunikatach w Springu . ................................................ 350 12.5.2. Asynchroniczne RPC z Lingo . ................................................................................... 352 12.6. Podsumowanie ........................................................................................................................... 354
10
Spis treci
Rozdzia 13. Zarzdzanie komponentami Springa za pomoc JMX
357
13.1. Eksportowanie komponentów Springa w formie MBean . .................................................... 358 13.1.1. Udostpnianie metod na podstawie nazwy . ............................................................. 361 13.1.2. Uycie interfejsów do definicji operacji i atrybutów komponentu zarzdzanego . .... 363 13.1.3. Praca z komponentami MBean sterowanymi adnotacjami . ..................................... 364 13.1.4. Postpowanie przy konfliktach nazw komponentów zarzdzanych . ....................... 365 13.2. Zdalny dostp do komponentów zarzdzanych . .................................................................... 366 13.2.1. Udostpnianie zdalnych komponentów MBean . ...................................................... 367 13.2.2. Dostp do zdalnego komponentu MBean . ............................................................... 367 13.2.3. Obiekty poredniczce komponentów zarzdzanych . .............................................. 369 13.3. Obsuga powiadomie . ............................................................................................................. 370 13.3.1. Odbieranie powiadomie . ......................................................................................... 371 13.4. Podsumowanie ........................................................................................................................... 372
Rozdzia 14. Pozostae zagadnienia
373
14.1. Wyodrbnianie konfiguracji . ................................................................................................... 374 14.1.1. Zastpowanie symboli zastpczych we waciwociach . .......................................... 374 14.1.2. Nadpisywanie waciwoci . ....................................................................................... 377 14.1.3. Szyfrowanie zewntrznych waciwoci . .................................................................. 378 14.2. Wizanie obiektów JNDI . ........................................................................................................ 380 14.2.1. Praca z tradycyjnym JNDI . ....................................................................................... 380 14.2.2. Wstrzykiwanie obiektów JNDI . ................................................................................ 382 14.2.3. Wizanie komponentów EJB w Springu . ................................................................. 385 14.3. Wysyanie wiadomoci e-mail . ................................................................................................. 386 14.3.1. Konfiguracja komponentu wysyajcego poczt . ...................................................... 386 14.3.2. Budowa wiadomoci e-mail . ...................................................................................... 388 14.4. Planowanie zada wykonywanych w tle . ................................................................................ 392 14.4.1. Deklaracja zaplanowanych metod . ............................................................................ 393 14.4.2. Deklaracja metod asynchronicznych . ....................................................................... 395 14.5. Podsumowanie ........................................................................................................................... 396 14.6. Koniec…? ................................................................................................................................... 396
Skorowidz
399
Przedmowa To niesamowite! Kiedy to pisz, niewiele brakuje do siedmiu lat od momentu wydania wersji 1.0 Springa, a take od chwili, gdy rozpoczlimy, Ryan Breidenbach i ja, prac nad pierwszym wydaniem tej ksiki. Kto by wówczas przypuszcza, e Spring zmieni programowanie w Javie w tak duym stopniu? W tamtym pierwszym wydaniu staralimy si, Ryan i ja, opisa kady szczegó frameworka Spring. W znacznej czci nam si to udao. Ca opowie o Springu zdoalimy wtedy bez problemu zamkn w 11 rozdziaach, ze wstrzykiwaniem zalenoci, programowaniem aspektowym, nieulotnoci, transakcjami Spring MVC i Acegi Security w rolach gównych. Oczywicie, opowie taka musiaa by wówczas wyraona za pomoc duych iloci kodu XML (czy kto jeszcze pamita, jak wygldao deklarowanie transakcji za pomoc komponentu TransactionProxyFactoryBean?). Do czasu, gdy zabieraem si za pisanie drugiego wydania, Spring nieco si rozrós. Ponownie próbowaem upchn wszystko w jednej ksice. Okazao si to niemoliwe. Spring osign rozmiary czego niemoliwego do opisania w ksice o 700 do 800 stronach. Waciwie cae kompletne rozdziay zostay wycite z drugiego wydania, poniewa zabrako dla nich miejsca. Ponad trzy lata i dwie wersje Springa miny od momentu ukazania si w druku drugiego wydania. Spring zajmuje wikszy obszar ni kiedykolwiek wczeniej i szczegóowe omówienie wszystkich zwizanych z nim projektów zajoby kilka tomów. Nie byoby moliwe pomieszczenie caej dostpnej wiedzy na temat Springa w pojedynczej ksice. Zatem nawet nie bd próbowa. Ksiki czsto staj si coraz grubsze z kadym kolejnym wydaniem. Lecz pewnie zauwaye, Czytelniku, e trzecie wydanie tej ksiki ma mniej stron ni drugie. Byo to moliwe z kilku powodów. Poniewa nie mogem zmieci wszystkiego w jednym tomie, dokonaem wyboru tematów, które trafiy do tego wydania. Postanowiem skupi si na tym, co uwaam za najbardziej podstawowe tematy w Springu, których znajomo przyda si prawie kademu, kto w nim programuje. Nie zamierzam przez to powiedzie , e pozostae tematy s niewane, lecz te zawarte w tej ksice stanowi podstawy programowania we frameworku Spring. Kolejnym powodem, dla którego to wydanie zawiera mniej stron, jest fakt, e podczas gdy obszar zastosowa Springa nadal szybko si rozrasta, kontynuowana take bya tendencja, by z kad kolejn wersj programowanie w nim byo coraz prostsze. Bogaty zbiór konfiguracyjnych przestrzeni nazw w Springu, adaptacja modeli programowania sterowanego adnotacjami, stosowanie rozsdnych konwencji i wartoci domylnych pozwoliy ograniczy rozmiar plików konfiguracyjnych Springa z wielu stron kodu XML do zaledwie kilku elementów w tym jzyku.
12
Przedmowa
Lecz niech Ci to nie zmyli, Czytelniku: cho liczba stron si zmniejszya, nadal zdoaem pomieci w nich wiele nowych, wartociowych rozwiza w Springu. Obok wstrzykiwania zalenoci, programowania aspektowego i deklaracyjnej obsugi transakcji, które Spring posiada od duszego czasu, od wydania drugiego wiele mechanizmów zostao dodanych lub w istotny sposób zmienio sposób dziaania. Oto niektóre z tych, których stosowania nauczymy si podczas lektury obecnego wydania: Q
Q
Q
Q
Q
Wizania komponentów na podstawie adnotacji, co w znaczcy sposób pozwolio ograniczy rozmiar plików konfiguracyjnych w jzyku XML. Nowy jzyk wyrae, pozwalajcy na wyznaczanie wartoci wizanych z waciwociami komponentów w sposób dynamiczny w czasie dziaania programu. Zupenie nowe, kontrolowane za pomoc adnotacji rodowisko Spring MVC, które jest znacznie bardziej elastyczne ni wczeniejsze rodowisko kontrolerów hierarchicznych. Zabezpieczanie aplikacji w Springu za pomoc Spring Security, znacznie atwiejsze dziki nowej konfiguracyjnej przestrzeni nazw, wygodnym wartociom domylnym i obsudze regu bezpieczestwa zorientowanych na wyraenia. Pierwszorzdna obsuga tworzenia i konsumowania zasobów REST, na bazie Spring MVC.
Niezalenie od tego, czy jeste, Czytelniku, nowicjuszem Springa, czy te weteranem, mam nadziej, e uznasz t ksik za niezastpiony przewodnik podczas korzystania ze Springa w swoich projektach.
Podzikowania Zanim wzie, Czytelniku, t ksik do rk, musiaa ona przej przez rce wielu innych osób — osób, które j redagoway, recenzoway, korygoway i zarzdzay caym procesem wydawniczym. Nie czytaby tej ksiki, gdyby nie zaangaowanie wszystkich tych osób. W pierwszej kolejnoci chciabym podzikowa wszystkim w wydawnictwie Manning za cik prac i za naciskanie na mnie, ebym to cholerne zadanie doprowadzi do koca, a take za dooenie stara, by ksika ta bya najlepsza, jak to tylko moliwe. Byli to: Marjan Bace, Michael Stephens, Christina Rudloff, Karen Tegtmeyer, Maureen Spencer, Mary Piergies, Sebastian Stirling, Benjamin Berg, Katie Tennant, Janet Vail oraz Dottie Marsico. W tym czasie par innych osób miao okazj przeczyta rkopis w pierwszej, roboczej wersji i dzielio si wraeniami, informujc mnie, co zrobiem dobrze, a gdzie „zgubiem” jak liter (uff). Ci wszyscy recenzenci zasuguj na wielkie podzikowania za ich cenne uwagi: Valentin Crettaz, Jeff Addison, John Ryan, Olivier Nouguier, Joshua White, Deiveehan Nallazhagappan, Adam Taft, Peter Pavlovich, Mykel Alvis, Rick Wagner, Patrick Steger, Josh Devins, Dan Alford, Alberto Lagna, Dan Dobrin, Robert Hanson, Chad Davis, Carol McDonald, Deepak Vohra oraz Robert O’Connor. Szczególnie dzikuj Dougowi Warrenowi za penienie obowizków redaktora technicznego i za to, e przesia wszystkie szczegóy techniczne tej ksiki przez bardzo drobne sito. Wdziczno jestem winny take osobom, które nie byy bezporednio zaangaowane w powstawanie tej ksiki, lecz byy w pobliu ze wsparciem, przyjani, dobr rozmow i upewniay si, e mam wystarczajco duo przerw w pisaniu, by móc jeszcze robi inne rzeczy. Przede wszystkim dzikuj mojej onie Raymie. Jeste moj najlepsz przyjaciók, mioci mojego ycia i powodem wszystkiego, co robi. Bardzo Ci kocham. Dzikuj za to, e zmierzya si z moim kolejnym projektem pisarskim i e jeste dla mnie wsparciem. Maisy i Madi, moje mae ksiniczki, dzikuj Wam za uciski, umiechy, wyobrani i czasami przerwy na granie w Mario Kart. Dzikuj moim kolegom ze SpringSource za cige rewolucjonizowanie sposobu, w jaki tworzymy oprogramowanie, i za umoliwienie mi uczestnictwa w tym, co robi. Szczególne podzikowania dla dwóch osób ze SpringSource, z którymi pracuj na co dzie, a s to Keith Donald i Roy Clarkson — w cigu minionego roku udao nam si zdziaa par niesamowitych rzeczy i czekam z niecierpliwoci na wspaniae rzeczy, które s przed nami. Wielkie dziki dla osób, z którymi wspótworz cykl konferencji No Fluff/Just Stuff, a s to: Ted Neward, Venkat Subramaniam, Tim Berglund, Matthew McCullough, Matt Stine, Brian Goetz, Jeff Brown, Dave Klein, Ken Sipe, Nathaniel Schutta, Neal Ford,
14
Podzikowania
Pratik Patel, Rohit Bhardwaj, Scott Davis, Mark Richards oraz oczywicie Jay Zimmerman. Dzikuj im za to, e co który weekend przypominaj mi, e nie jestem ani w czci tak mdry jak oni. Na koniec, jest wiele innych osób, o których wpywie na ksztatowanie si mojej osobowoci, kariery oraz tej ksiki nie mog zapomnie . S to: Ryan Breidenbach, Ben Rady, Mike Nash, Matt Smith, John Woodward, Greg Vaughn, Barry Rogers, Paul Holser, Derek Lane, Erik Weibust oraz Andrew Rubalcaba.
O ksice Framework Spring powsta z myl o bardzo konkretnym celu — by uatwi tworzenie aplikacji w Java EE. Idc tym samym tropem, ksika Spring w Akcji. Wydanie III zostaa napisana, by uatwi nauk korzystania ze Springa. Nie byo moim celem przedstawienie Ci, Czytelniku, szczegóowego listingu Spring API. Zamiast tego mam nadziej przedstawi framework Spring w sposób, który jest najbardziej odpowiedni dla programujcych w Java EE, dziki uyciu praktycznych przykadów kodu opisujcych zjawiska z rzeczywistego wiata. Poniewa Spring jest rodowiskiem moduowym, moduowy jest take ukad treci w tej ksice. Zdaj sobie spraw, e nie wszyscy programici maj takie same potrzeby. Niektórzy bd chcieli nauczy si frameworka Spring od podstaw, podczas gdy inni bd woleli wybra na pocztek inne tematy i zapoznawa si z nimi w zmienionej kolejnoci. W ten sposób ksika moe suy jako narzdzie do nauki Springa dla pocztkujcych, a take jako przewodnik i punkt odniesienia dla tych, którzy zechc zagbi si bardziej w jak specyficzn funkcjonalno .
Dla kogo ta ksika Ksika Spring w Akcji. Wydanie III jest adresowana do wszystkich programujcych w jzyku Java, lecz szczególnie uyteczna bdzie dla twórców oprogramowania klasy enterprise w Javie. Bd Ci, Czytelniku, prowadzi za pomoc przykadów kodu, których zoono bdzie agodnie wzrasta . Jednak prawdziwa moc Springa polega na moliwoci jego uycia do uatwienia pracy programistom tworzcym aplikacje biznesowe. Zatem twórcy oprogramowania klasy enterprise w najwikszym stopniu zdoaj skorzysta z przykadów przedstawionych w tej ksice. Poniewa znaczna cz Springa jest powicona realizacji usug klasy enterpise, istnieje wiele podobiestw midzy Springiem i EJB. Zatem wszelkie dowiadczenie na tym polu, jakie posiadasz, Czytelniku, bdzie przydatne do porównania tych dwóch rodowisk. Cz ksiki zostaa powicona temu tematowi. Waciwie, w ostatnich piciu rozdziaach zademonstrowaem sposób, w jaki Spring wspiera integracj biznesow aplikacji internetowych. Jeli jeste, Czytelniku, twórc aplikacji klasy enterprise, uznasz ostatni cz tej ksiki za szczególnie wartociow.
Plan dziaania Ksika Spring w Akcji. Wydanie III jest podzielona na trzy czci. Cz pierwsza wprowadza w podstawy frameworka Spring. W czci drugiej uczynimy kolejny krok, zagbiajc si w najczciej uywane elementy aplikacji w Springu. Ostatnia cz demonstruje moliwo uycia Springa podczas integracji z innymi aplikacjami lub usugami.
16
O ksice
W czci 1. poznamy wstrzykiwanie zalenoci (ang. Dependency Injection, DI) oraz programowanie aspektowe (ang. Aspect Oriented Programming, AOP), dwa podstawowe mechanizmy frameworka Spring. To pozwoli nam na dobre zrozumienie zupenych podstaw Springa, z których bdziemy nieustannie korzysta w caej ksice. Rozdzia 1. jest wprowadzeniem do DI oraz AOP. Omówimy w nim zastosowanie tych dwóch technik w celu uzyskania lunego wizania w aplikacjach Javy. W rozdziale 2. w bardziej szczegóowy sposób przygldamy si sposobowi konfigurowania i kojarzenia obiektów naszej aplikacji za pomoc wstrzykiwania zalenoci. Nauczymy si pisa luno wizane komponenty, a take wiza ich zalenoci i waciwoci wewntrz kontenera Springa za pomoc plików XML. Gdy ju opanujemy podstawy konfiguracji Springa w jzyku XML, rozdzia 3. pozwoli nam zapozna si z adnotacjami, jako sposobem konfiguracji alternatywnym wobec plików XML. Rozdzia 4. pozwoli nam zgbi zastosowania programowania aspektowego do izolowania zagadnie przecinajcych od obiektów, na które wpywaj. Rozdzia ten stanowi take przygotowanie do lektury dalszych rozdziaów, w których posuymy si programowaniem aspektowym do realizacji w sposób deklaratywny takich usug jak transakcje, bezpieczestwo i pami podrczna. Cze 2. bazuje na wprowadzonych w czci 1. mechanizmach wstrzykiwania zalenoci oraz programowania aspektowego i demonstruje sposób zastosowania tych koncepcji podczas konstruowania elementów powszechnie wystpujcych w aplikacjach. W rozdziale 5. zostaa omówiona obsuga nieulotnoci danych w Springu. Otrzymasz, Czytelniku, wprowadzenie do obsugi JDBC w Springu, rozwizanej w sposób pozwalajcy unikn stosowania wikszoci kodu szablonowego zwizanego z JDBC. Zostanie take omówiona integracja Springa ze rodowiskami zapewniajcymi nieulotno danych, takimi jak Hibernate oraz Java Persistance API (JPA). Rozdzia 6. stanowi uzupenienie rozdziau 5., demonstrujc, jak zapewni integralno naszej bazy danych za pomoc obsugi transakcji w Springu. Przekonamy si, w jaki sposób programowanie aspektowe w Springu pozwala prostym obiektom aplikacji korzysta z potencjau transakcji deklaracyjnych. W rozdziale 7. znajduje si wprowadzenie do frameworka aplikacji internetowych MVC w Springu. Dowiemy si, jak Spring moe w przeroczysty sposób wiza parametry aplikacji internetowych z naszymi obiektami biznesowymi, zapewniajc jednoczenie kontrol poprawnoci i obsug bdów. Dowiemy si, jak atwo dodawa nowe funkcje do aplikacji internetowych za pomoc kontrolerów MVC w Springu. Rozdzia 8. zawiera omówienie Spring Web Flow, rozszerzenia do Spring MVC, które pozwala na konstruowanie konwersacyjnych aplikacji internetowych. W rozdziale tym nauczymy si tworzenia aplikacji internetowych, które prowadz uytkownika podczas okrelonej wymiany danych. W rozdziale 9. nauczymy si, jak zastosowa mechanizmy bezpieczestwa w naszych aplikacjach za pomoc Spring Security. Dowiemy si, w jaki sposób Spring Security zabezpiecza aplikacje, zarówno na poziomie da webowych za pomoc filtrów serwletów, jak i na poziomie metod za pomoc programowania aspektowego. Po skonstruowaniu aplikacji za pomoc wszystkiego, czego nauczylimy si w czci 2., moemy zdecydowa si na zintegrowanie jej z innymi aplikacjami lub usugami. W czci 3. nauczymy si, jak uzyska taki efekt.
Konwencje zapisu kodu
17
Rozdzia 10. zawiera omówienie sposobu publikowania obiektów naszej aplikacji jako usug zdalnych. W rozdziale tym dowiemy si take, jak, zachowujc pynno dziaania, korzysta z usug zdalnych, jakby byy zwykymi obiektami w naszej aplikacji. Wród technologii zdalnych, jakie poznamy, znajd si RMI, Hessian/Burlap, usugi sieciowe oparte na protokole SOAP oraz wasny mechanizm Springa o nazwie HttpInvoker. W rozdziale 11. wrócimy do frameworka Spring MVC, demonstrujc sposób jego zastosowania podczas publikowania danych naszej aplikacji jako zasobów zgodnych z wzorcem REST. Dodatkowo nauczymy si konstruowa klienty REST za pomoc wzorca RestTemplate w Springu. Podczas lektury rozdziau 12. przyjrzymy si zastosowaniu Springa do wysyania i odbierania wiadomoci asynchronicznych za pomoc JMS. Poza podstawowymi operacjami z JMS w Springu, dowiemy si te, jak — korzystajc z projektu open source, zwanego Lingo — publikowa i konsumowa asynchronicznie usugi zdalne za pomoc JMS. W rozdziale 13. dowiemy si, jak zastosowa JMX w Springu, by kolejkowa zadania, wysya e-maile, korzysta z zasobów skonfigurowanych za pomoc interfejsu JNDI i zarzdza obiektami naszej aplikacji. Koczc rozdziaem 14. nasze poznawanie Springa, dowiemy si, jak uy go do kolejkowania zada, wysyania e-maili i dostpu do zasobów skonfigurowanych za pomoc interfejsu JNDI.
Konwencje zapisu kodu W ksice tej znajduje si wiele przykadów kodu. Przykady te zostay zapisane czcionk o staej szerokoci. Jeli na jaki fragment w przykadzie chciaem zwróci szczególn uwag czytelników, zosta on pogrubiony w kodzie. Wystpujce w tekcie ksiki nazwy klas, metod oraz fragmenty w jzyku XML take zostay wyrónione zapisem za pomoc czcionki o staej szerokoci. Wiele sporód klas i pakietów Springa posiada wyjtkowo dugie (cho uatwiajce zrozumienie) nazwy. Z tego powodu w niektórych miejscach pojawia si potrzeba uycia znaku kontynuacji wiersza (´). Nie wszystkie przykady kodu w tej ksice bd kompletne. Czsto pokazano tylko metod lub dwie z klasy, by skupi si na okrelonym temacie. Kompletne kody ródowe aplikacji omawianych w tej ksice mona znale na stronie internetowej, pod adresem www.helion.pl/ksiazki/sprwa3.htm.
O autorze Craig Walls jest twórc oprogramowania, posiadajcym ponad 13-letnie dowiadczenie. Jest take wspóautorem ksiki XDoclet in Action (wyd. Manning, 2003) oraz dwóch poprzednich wyda tej ksiki, nietumaczonych na jzyk polski (wyd. Manning, 2005 i 2007). Gorliwie promuje framework Spring, czsto przemawiajc na spotkaniach lokalnych grup uytkowników lub na konferencjach i piszc o Springu w swoim blogu. Craig, gdy nie jest zajty dubaniem w kodzie, spdza tak wiele czasu, jak tylko moe, ze swoj on, dwiema córkami, szecioma ptakami, czterema psami, dwoma kotami i nieustannie zmieniajc si liczb egzotycznych rybek. Craig mieszka w miejscowoci Plano w stanie Teksas.
18
O ksice
O tytule czc wprowadzenia, ogld caoci i przykady konkretnych rozwiza, ksiki z serii W akcji zostay zaprojektowane jako pomoc w nauce i zapamitywaniu. Zgodnie z badaniami naukowymi w dziedzinie ludzkiego poznania, elementami, które ludzie najlepiej zapamituj, s te, które odkryli podczas samodzielnie motywowanych poszukiwa. Cho w wydawnictwie Manning nie jestemy ekspertami w nauce zajmujcej si ludzkim poznaniem, jestemy przekonani, e funkcjonujc w sytuacji zmuszajcej do ustawicznej nauki, trzeba przechodzi przez etapy poszukiwa, zabawy i, co ciekawe, powtarzania tego, czego ju si nauczylimy. Ludzie ucz si w czasie dziaania, „w akcji” (ang. in action — std tytu serii). Istotn czci poradnika z serii W akcji jest silne nastawienie na przykady. Zachca to czytelników do samodzielnego próbowania omawianych rozwiza, zabawy z nowym kodem i badania nowych koncepcji. Jest jeszcze jedna, bardziej przyziemna przyczyna nadania serii ksiek takiej wanie nazwy: nasi czytelnicy s bardzo zajci. Korzystaj z ksiki, by wykona prac albo rozwiza jaki problem. Potrzebuj ksiek pozwalajcych na bezproblemowe zapoznawanie si z ich treci „z doskoku” i korzystanie tylko z potrzebnego fragmentu, tylko wtedy, gdy taka potrzeba wystpi. Potrzebuj oni ksiek, które pomog im „w akcji”. Ksiki z tej serii zostay zaprojektowane dla takich wanie czytelników.
Cz 1 Podstawy frameworka Spring
F
ramework Spring wykonuje wiele czynnoci. Lecz gdybymy wyodrbnili jego podstawowe elementy, najwaniejszymi funkcjami Springa s: wstrzykiwanie zalenoci (ang. dependency injection, DI) i programowanie aspektowe (ang. aspect-oriented programming, AOP). Rozpoczynajc od rozdziau 1., „Zrywamy si do dziaania”, podamy krótki przegld uycia DI oraz AOP w Springu, a take zademonstrujemy ich uyteczno podczas izolowania obiektów w aplikacji. W rozdziale 2., „Tworzymy powizania midzy komponentami”, poznamy dokadniej sposób zastosowania w Springu konfiguracji bazujcej na jzyku XML w celu zapewnienia obiektom w aplikacji lunego wizania za pomoc wstrzykiwania zalenoci. Nauczymy si definiowa obiekty aplikacji, a nastpnie zapewnia im komunikacj za pomoc zalenoci midzy nimi. XML nie jest jedynym sposobem, w jaki moe by konfigurowany Spring. Podejmujc temat w miejscu, gdzie zakoczy si poprzedni rozdzia, w rozdziale 3., „Ograniczamy uycie jzyka XML w konfiguracji Springa”, poznamy niektóre nowe moliwoci w Springu, pozwalajce na zapewnianie obiektom komunikacji z niewielkim tylko uyciem jzyka XML (a w niektórych przypadkach zupenie bez niego). W rozdziale 4., „Aspektowy Spring”, poznamy sposób uycia programowania aspektowego w rodowisku Spring w celu odizolowania usug systemowych (takich jak bezpieczestwo czy audyt) od obiektów, które z nich korzystaj. Ten rozdzia bdzie punktem wyjcia dla rozdziaów 6. i 9., w których nauczymy si sposobów deklarowania transakcji i zapewniania bezpieczestwa.
Zrywamy si do dziaania
W tym rozdziale omówimy: Q
Zapoznanie si z podstawowymi moduami frameworka Spring
Q
Izolowanie obiektów w aplikacji
Q
Zarzdzanie problemami przekrojowymi za pomoc programowania aspektowego
Q
Kontener dla komponentów we frameworku Spring
Wszystko zaczo si od komponentu. W roku 1996 jzyk programowania Java by jeszcze now, ekscytujc i dopiero zaczynajc zdobywa popularno platform. Wielu programistów przechodzio na ten jzyk, bo zobaczyli, jak tworzy bogate i dynamiczne aplikacje internetowe z wykorzystaniem apletów. Wkrótce dowiedzieli si, e ten dziwny nowy jzyk ma do zaoferowania wicej ni animowanie onglujcych postaci z kreskówek. W odrónieniu od jakiegokolwiek wczeniejszego jzyka programowania, jzyk Java umoliwi pisanie zoonych aplikacji zbudowanych z prostych elementów. Nowych programistów przycigay aplety, jednak to komponenty zatrzymay ich na duej. W grudniu tego samego roku firma Sun Microsystems opublikowaa dokument JavaBeans 1.00-A specification. JavaBeans bya to definicja modelu komponentów oprogramowania dla Javy. Specyfikacja ta okrelia zestaw praktyk programistycznych, które umoliwiy tworzenie w Javie prostych obiektów wielokrotnego uytku i czenie ich w atwy sposób w celu konstruowania bardziej skomplikowanych aplikacji. Chocia JavaBeans zostay pomylane jako rodek ogólnego przeznaczenia sucy do definiowania komponentów aplikacji wielokrotnego uytku, pocztkowo zostay uyte jako model do budowy elementów interfejsu uytkownika. Wydaway si zbyt proste, by nadaway si do jakiejkolwiek „prawdziwej” pracy. Twórcy oprogramowania klasy enterprise chcieli wicej.
22
ROZDZIA 1. Zrywamy si do dziaania
Zaawansowane aplikacje czsto potrzebuj usug takich jak obsuga transakcji, bezpieczestwo czy przetwarzanie rozproszone — których nie zapewnia bezporednio specyfikacja JavaBeans. Zatem w marcu roku 1998 firma Sun opublikowaa wersj 1.0 specyfikacji Enterprise JavaBeans (EJB). Specyfikacja ta rozszerzya pojcie komponentu jzyka Java na stron serwera, zapewniajc tak bardzo potrzebne usugi klasy enterprise, lecz nie zdoaa kontynuowa prostoty pierwotnej specyfikacji JavaBeans. Poza nazw EJB czy z oryginaln specyfikacj JavaBeans niewiele podobiestw. Mimo faktu, e wiele aplikacji zostao z powodzeniem zbudowanych na bazie EJB, ten model komponentów nigdy nie zdoa speni postawionego przed nim zadania: uproszczenia procesu tworzenia aplikacji klasy enterprise. To prawda, e deklaracyjny model programowania upraszcza wiele infrastrukturalnych aspektów programowania, takich jak transakcje czy bezpieczestwo. Lecz EJB komplikuje programowanie w inny sposób, przez wymaganie deskryptorów wdroenia i zmuszanie do „grzebania we wntrznociach” kodu (interfejsy lokalne i zdalne). Z biegiem czasu wielu programistów poczuo rozczarowanie modelem EJB. W efekcie jego popularno w ostatnich latach zmalaa, pozostawiajc wielu programistów poszukujcych atwiejszego sposobu. W dzisiejszych czasach rozwój komponentów Javy powróci do róde. Nowe techniki programistyczne, w tym programowanie aspektowe (AOP) i wstrzykiwanie zalenoci (DI), zapewniy komponentom JavaBeans sporo z potencjau wczeniej zarezerwowanego dla EJB. Te techniki umoliwiaj zwykym starym obiektom Javy (ang. Plain Old Java Obiects, POJO) korzystanie z deklaratywnego modelu programowania, przypominajcego ten w EJB, lecz bez caej wystpujcej w EJB zoonoci. Ju nie trzeba ucieka si do pisania nieporcznych komponentów EJB, gdy prosty JavaBean jest wystarczajcy. Bdmy sprawiedliwi — take EJB ewoluoway w kierunku promowania modelu programowania bazujcego na POJO. Wykorzystujc pomysy takie jak DI czy AOP, najnowsza specyfikacja EJB jest znaczco prostsza od poprzednich. Lecz dla wielu programistów jest to zbyt may ruch i zbyt spóniony. Do momentu wejcia w ycie specyfikacji EJB 3, inne frameworki bazujce na POJO ugruntoway sw pozycj jako de facto standardy w rodowisku programistów Javy. Na czoo wród lekkich rodowisk opartych na programowaniu POJO wysun si framework Spring, który bdziemy poznawali w tej ksice. Ten rozdzia powicimy przyjrzeniu si frameworkowi Spring na wysokim poziomie, dajc Ci, Czytelniku, pogld na to, do czego w ogóle suy Spring. Rozdzia ten da niez orientacj w typach problemów, jakie pozwala rozwiza Spring, i bdzie stanowi podstaw dla reszty ksiki. Ale po kolei — dowiedzmy si, o co chodzi z caym tym Springiem.
1.1.
Upraszczamy programowanie w Javie Spring jest frameworkiem open source, zaproponowanym przez Roda Johnsona i opisanym w jego ksice Expert One-on-One: J2EE Design and Development. Spring zosta utworzony, by upora si ze zoonoci programowania aplikacji klasy enterprise i umoliwi osignicie za pomoc zwykych, prostych komponentów JavaBean efektów wczeniej zarezerwowanych wycznie dla EJB. Lecz Spring jest uyteczny nie tylko podczas programowania aplikacji dziaajcych po stronie serwera. Piszc dowoln aplikacj w Javie, moemy czerpa korzyci z uycia frameworka Spring — zyskujc na prostocie, atwoci testowania i lunych powizaniach midzy obiektami.
1.1.
23
Upraszczamy programowanie w Javie BEAN POD INN NAZW… Chocia uytkownicy Springa, odwoujc
si do komponentów aplikacji, posuguj si zwrotami „komponent bean” oraz „komponent JavaBean” w znaczeniu dosownym, nie oznacza to, e komponenty w Springu musz cile wypenia specyfikacj JavaBeans. Komponenty te mog by dowolnym typem POJO. W tej ksice przyjmiemy do swobodn definicj pojcia JavaBean jako synonimu POJO. Jak si przekonamy podczas lektury tej ksiki, framework Spring wykonuje wiele czynnoci. Jednak u podstaw prawie wszystkiego, co umoliwia Spring, ley kilka fundamentalnych idei, a wszystkie skupione na podstawowym zadaniu tego rodowiska: Spring upraszcza programowanie w Javie. To miae stwierdzenie! Wiele frameworków obiecuje uproszczenie tego czy tamtego. Lecz Spring ma za zadanie uproci samo zadanie programowania w Javie. To wymaga dalszych wyjanie. Przygotowujc atak na zoono programowania w Javie, Spring korzysta z czterech kluczowych strategii: Q
Q Q Q
programowanie lekkie i niezbyt „inwazyjne” dziki uyciu zwykych prostych obiektów Javy (POJO); lune wizanie dziki wstrzykiwaniu zalenoci i zorientowaniu na interfejs; programowanie deklaratywne z uyciem aspektów i wspólnych konwencji; ograniczenie koniecznoci wielokrotnego pisania tego samego kodu dziki aspektom i wzorcom.
Prawie wszystko, co mona osign we frameworku Spring, da si sprowadzi do zastosowania jednej lub kilku z tych strategii. W dalszej czci tego rozdziau rozwiniemy kad z powyszych koncepcji, pokazujc na konkretnych przykadach, jak dobrze Spring radzi sobie ze spenianiem obietnicy uproszczenia programowania w Javie. Rozpocznijmy od przekonania si, w jaki sposób Spring zachowa minimaln inwazyjno dziki wykorzystaniu programowania bazujcego na POJO. 1.1.1.
Uwalniamy moc zawart w POJO
Jeli programujesz w Javie od dugiego czasu, prawdopodobnie widziae frameworki (a moe nawet pracowae w którym z nich), które ograniczay Ci, wymuszajc rozszerzanie której z wbudowanych w nie klas albo implementacj jakiego interfejsu. Klasycznym przykadem jest bezstanowy komponent sesyjny z czasów EJB 2. Jak wida na prostym przykadzie klasy HelloWorldBean, pokazanym na listingu 1.1, specyfikacja EJB2 zawieraa do wygórowane wymagania: Listing 1.1. Specyfikacja EJB 2.1 zmuszaa do implementowania metod, których nie potrzebowalimy
package com.habuma.ejb.session; import javax.ejb.SessionBean; import javax.ejb.SessionContext; public class HelloWorldBean implements SessionBean{ public void ejbActivate(){ }
Dlaczego wymagane jest deklarowanie tych metod?
24
ROZDZIA 1. Zrywamy si do dziaania public void ejbPassivate(){ } public void ejbRemove(){ } public void setSessionContext(SessionContext ctx){ } public String sayHello(){ return "Witaj wiecie"; }
Podstawowa logika biznesowa w EJB
public void ejbCreate(){ } }
Interfejs SessionBean pozwala wczy aplikacj w cykl ycia EJB, jeli zaimplementujemy kilka metod zwrotnych cyklu ycia (to te metody, których nazwy zaczynaj si od ejb). Parafrazujc, powinnimy powiedzie , e interfejs SessionBean zmusza nas do wczenia aplikacji w cykl ycia EJB, nawet jeli tego nie potrzebujemy. Wikszo kodu w HelloWorldBean znalaza si tam wycznie ze wzgldu na rodowisko. To rodzi pytanie: kto komu suy? rodowisko EJB 2 nie miao wycznoci na tak „inwazyjno ”. Inne popularne frameworki, takie jak wczeniejsze wersje Struts, WebWork czy Tapestry, take obciay sob skdind proste klasy Javy. Te cikie rodowiska zmuszay programistów do pisania klas zamieconych niepotrzebnym kodem, uwizionych w danym frameworku i czsto trudnych do testowania. Spring unika (tak bardzo, jak to tylko moliwe) zamiecania kodu naszej aplikacji swoim API. Prawie nigdy nie bdziemy zmuszani do implementowania charakterystycznego dla Springa interfejsu lub rozszerzania zawartej w nim klasy. Przeciwnie, klasy w aplikacji bazujcej na Springu czsto w aden sposób nie wskazuj na fakt korzystania z tego frameworka. W najgorszym razie mog zosta opatrzone jedn z adnotacji Springa, lecz poza tym pozostaj zwykymi POJO. Gdybymy przepisali klas HelloWorldBean, pokazan na listingu 1.1, by dziaaa jako komponent zarzdzany przez Springa, mogaby wyglda jak na listingu 1.2. Listing 1.2. Spring nie da umieszczania niczego w HelloWorldBean bez powodu
package com.habuma.spring; public class HelloWorldBean{ public String sayHello(){ return "Witaj wiecie"; } }
To wszystko, czego potrzebowalimy
Czy tak nie jest lepiej? Wszystkie te haaliwe metody zwizane z cyklem ycia znikny. HelloWorldBean nie implementuje, nie rozszerza, ani nawet nie importuje niczego ze Spring API. HelloWorldBean jest lekkim, przecitnym i w kadym znaczeniu tego zwrotu zwykym starym obiektem Javy.
1.1.
Upraszczamy programowanie w Javie
25
Mimo swojej prostoty POJO mog by potne. Jednym ze sposobów, w jaki Spring zwiksza moliwoci POJO, jest czenie ich za pomoc wstrzykiwania zalenoci. Przekonajmy si, w jaki sposób mona dziki tej technice uzyska lune wizanie midzy obiektami. 1.1.2.
Wstrzykujemy zalenoci
Zwrot wstrzykiwanie zale noci moe brzmie oniemielajco, budzc skojarzenia z jak skomplikowan technik programistyczn albo wzorcem projektowym. Lecz okazuje si, e DI nie jest ani troch tak skomplikowane, jak brzmi jego nazwa. Stosujc DI w swoich projektach, zauwaymy, e nasz kod staje si znaczco prostszy, atwiejszy do zrozumienia i do testowania. Kada niebanalna aplikacja (prawie kada bardziej skomplikowana ni przykad Witaj wiecie) jest skonstruowana z dwóch lub wicej klas, które wspópracuj midzy sob, by realizowa jak logik biznesow. Tradycyjnie kady obiekt jest odpowiedzialny za przechowywanie referencji do obiektów, z którymi wspópracuje (swoich zalenoci). Moe to prowadzi do bardzo silnie powizanego i trudnego do testowania kodu. Jako przykad rozwamy klas Knight (rycerz) pokazan na listingu 1.3. Listing 1.3. Rycerz nalecy do klasy DamselRescuingKnight moe si podj tylko misji RescueDamselQuest
package com.springinaction.knights; public class DamselRescuingKnight implements Knight{ private RescueDamselQuest quest; public DamselRescuingKnight(){ quest=New RescueDamselQuest(); }
cise powizanie z misj RescueDamselQuest
public void embarkOnQuest()throws QuestException{ quest.embark(); } }
Jak widzimy, DamselRescuingKnight (rycerz ratujcy niewiasty) tworzy sobie quest (misj), RescueDamselQuest (misja ratowania niewiasty), wewntrz konstruktora. W ten sposób klasa DamselRescuingKnight jest cile powizana z misj RescueDamselQuest i ma bardzo ograniczony repertuar misji, jakich moe si podj . Jeli jest jaka niewiasta, któr trzeba uratowa , rycerz jest gotów do dziaania. Lecz jeli pojawi si smok, którego trzeba pokona , czy okrgy stó, który trzeba… powiedzmy… zaokrgli , wówczas nasz rycerz bdzie siedzia bezczynnie. Co wicej, bdzie strasznie trudno napisa test moduowy dla klasy DamselRescuing ´Knight. Podczas takiego testu chcielibymy mie moliwo stwierdzenia, e faktycznie wywoanie dla rycerza metody embarkOnQuest() skutkuje wywoaniem metody embark() dla misji. Lecz nie istnieje naturalny sposób, by w tym miejscu osign taki efekt. Niestety, klasa DamselRescuingKnight pozostanie nieprzetestowana. Wizanie obiektów jest dwugow besti. Z jednej strony, cile powizany kod jest trudny do testowania, trudny do ponownego uycia, trudny do zrozumienia, a usuwanie
26
ROZDZIA 1. Zrywamy si do dziaania
bdów przypomina polowanie na mole z uyciem packi (poprawienie jednego bdu skutkuje pojawieniem si jednego lub kilku bdów gdzie indziej). Z drugiej strony, pewna liczba powiza jest konieczna — zupenie niepowizany kod niczego nie robi. Aby móc wykonywa jakkolwiek uyteczn czynno , klasy musz w jaki sposób wiedzie o sobie nawzajem. Wizanie obiektów jest konieczne, lecz naley nim zarzdza z du ostronoci. Z kolei gdy skorzystamy z techniki DI, obiekty otrzymaj swoje zalenoci w momencie utworzenia od swego rodzaju „osoby trzeciej”, która koordynuje kady z obiektów w systemie. Nie wymagamy od obiektów, by tworzyy swoje zalenoci lub uzyskiway informacje o nich. Zamiast tego zalenoci s do obiektów wstrzykiwane, kiedy okazuj si potrzebne. W uproszczony sposób wstrzykiwanie zalenoci poRysunek 1.1. Wstrzykiwanie kazano na rysunku 1.1. zalenoci polega By zilustrowa ten punkt, spójrzmy na klas Brave na podawaniu obiektom ´Knight (dzielny rycerz) na listingu 1.4. Rycerz nie ich zalenoci zamiast tylko jest dzielny, lecz take zdolny do podjcia si zmuszania ich, by same te zalenoci uzyskiway kadej misji, jak otrzyma. Listing 1.4. Dzielny rycerz jest wystarczajco elastyczny, by zaj si kad otrzyman misj
package com.springinaction.knights; public class BraveKnight implements Knight{ private Quest quest; public BraveKnight(Quest quest){ this.quest=quest; }
Wstrzyknicie misji
public void embarkOnQuest()throwsQuestException{ quest.embark(); } }
Jak widzimy, w odrónieniu od klasy DamselRescuingKnight klasa BraveKnight nie tworzy sobie misji. Zamiast tego otrzymuje misj, gdy jest tworzony obiekt tej klasy — jako argument jej konstruktora. Jest to typ wstrzykiwania zalenoci, znany jako wstrzykiwanie przez konstruktor. Co wicej, misja, któr otrzymuje rycerz, jest typu Quest — interfejsu, który implementuj wszystkie misje. Zatem nasz dzielny rycerz moe podj si misji typu Rescue ´DamselQuest (ratowanie niewiasty), SlayDragonQuest (zgadzenie smoka), MakeRoundTa ´bleRounder (zaokrglanie okrgego stou) lub dowolnej innej, bdcej implementacj interfejsu Quest, jak otrzyma. Chodzi o to, e klasa BraveKnight nie jest powizana z adn konkretn implementacj interfejsu Quest. Dla rycerza nie ma znaczenia, jakiego rodzaju misji przyszo mu si podj , dopóki implementuje ona interfejs Quest. Jest to gówna zaleta techniki DI — lune
1.1.
27
Upraszczamy programowanie w Javie
wizanie. Jeli obiekt zna swoje zalenoci tylko z interfejsu (nie za z implementacji czy instancji), wówczas zaleno moe zosta zastpiona inn implementacj, a zalecy od niej obiekt nawet nie zauway rónicy. Jednym z najpopularniejszych sposobów podmiany zalenoci jest pozorna implementacja na czas testów. Nie bylimy w stanie odpowiednio przetestowa klasy Damsel ´RescuingKight z powodu jej cisego wizania. Lecz moemy atwo przetestowa klas BraveKnight, podajc jej pozorn implementacj interfejsu Quest, jak poniej na listingu 1.5. Listing 1.5. Aby przetestowa klas BraveKnight, wstrzykujemy do niej pozorn implementacj interfejsu Quest
package com.springinaction.knights; import static org.mockito.Mockito.*; import org.junit.Test; public class BraveKnightTest{ @Test public void knightShouldEmbarkOnQuest()throws QuestException{ Quest mockQuest=mock(Quest.class); Tworzymy pozorn implementacj interfejsu Quest
BraveKnight knight=New BraveKnight(mockQuest); knight.embarkOnQuest();
Wstrzykujemy pozorn implementacj interfejsu Quest
verify(mockQuest,times(1)).embark(); } }
Korzystamy tu z frameworka pozornych obiektów zwanego Mockito, by utworzy pozorn implementacj interfejsu Quest. Gdy mamy ju do dyspozycji pozorny obiekt, tworzymy now instancj klasy BraveKnight, wstrzykujc jej pozorn implementacj interfejsu Quest przez konstruktor. Po wywoaniu metody embarkOnQuest() moemy uy frameworka Mockito do weryfikacji, czy naleca do pozornej implementacji interfejsu Quest metoda embark() zostaa wywoana dokadnie raz. WSTRZYKUJEMY RYCERZOWI MISJ Gdy nasza klasa BraveKnight zostaa napisana w taki sposób, e moemy jej zleci dowoln
misj, w jaki wówczas sposób wskaemy, jak misj zlecimy rycerzowi? Czynno kojarzenia ze sob komponentów czsto jest okrelana nazw wizanie. Spring daje nam wiele sposobów na wizanie komponentów ze sob, lecz zawsze popularne byo zastosowanie w tym celu jzyka XML. Na listingu 1.6 pokazano prosty plik konfiguracyjny Springa, knights.xml, za pomoc którego zlecamy dzielnemu rycerzowi misj SlayDragonQuest. Listing 1.6. Wstrzykujemy w Springu misj SlayDragonQuest do obiektu klasy BraveKnight
28
ROZDZIA 1. Zrywamy si do dziaania xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
Wstrzykujemy komponent o nazwie quest
Tworzymy misj SlayDragonQuest
Jest to proste podejcie do wizania komponentów w Springu. Nie skupiajmy si w tej chwili za bardzo na szczegóach. Zakopiemy si gbiej w konfiguracj Springa i przekonamy si, co si dokadnie dzieje, gdy dojdziemy do rozdziau 2. Przyjrzymy si te innym sposobom wizania komponentów w Springu. Gdy ju zdeklarowalimy relacj midzy dzielnym rycerzem a misj, pora zaadowa plik XML z konfiguracj i „odpali ” aplikacj. OGLDAMY APLIKACJ W DZIAANIU
Podczas uruchamiania aplikacji w Springu kontekst aplikacji aduje definicje komponentów i realizuje ich powizania. W Springu kontekst aplikacji jest w peni odpowiedzialny za tworzenie i wizanie obiektów tworzcych aplikacj. Spring posiada kilka implementacji swojego kontekstu aplikacji, gównie rónicych si sposobem adowania przez nie konfiguracji. Poniewa plik knights.xml, w którym zdeklarowalimy komponenty, jest plikiem w jzyku XML, odpowiednim wyborem kontekstu moe by ClassPathXmlApplication ´Context. Ta implementacja kontekstu aduje konfiguracj z jednego lub wicej plików XML znajdujcych si w ciece klas aplikacji. Metoda main() na listingu 1.7 uywa implementacji ClassPathXmlApplicationContext do zaadowania pliku knights.xml i uzyskania referencji do obiektu Knight. Listing 1.7. Plik KnightMain.java aduje kontekst Springa zawierajcy opis rycerza
package com.springinaction.knights; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class KnightMain{ public static void main(String[]args){ ApplicationContextcontext= new ClassPathXmlApplicationContext("knights.xml"); Knight knight=(Knight)context.getBean("knight"); knight.embarkOnQuest();
adujemy kontekst Springa Uzyskujemy komponent knight
Korzystamy z komponentu knight
} }
Metoda main() tworzy tu kontekst aplikacji w Springu na podstawie pliku knights.xml. Nastpnie uywa kontekstu aplikacji jako fabryki, by uzyska komponent, który bdzie
1.1.
Upraszczamy programowanie w Javie
29
mia nazw knight. Majc referencj do obiektu typu Knight, wywouje metod embark ´OnQuest(), aby rycerz podj si misji, któr otrzyma. Zauwamy, e ta klasa nie posiada adnych informacji, jaki rodzaj misji otrzyma nasz bohater. Jeli idzie o ciso , pozostaje take w bogiej niewiadomoci, e ma do czynienia z obiektem klasy BraveKnight. Jedynie plik knights.xml posiada pewn informacj, z jakimi implementacjami mamy do czynienia. W tym miejscu koczy si krótkie wprowadzenie do wstrzykiwania zalenoci. Podczas lektury tej ksiki dowiemy si o technice DI znacznie wicej. Lecz gdyby, Czytelniku, potrzebowa jeszcze wicej informacji o wstrzykiwaniu zalenoci, polecam ksik autorstwa Dhanji R. Prasanna pod tytuem Dependency Injection, która opisuje technik DI a do najdrobniejszego szczegóu. Lecz teraz przyjrzyjmy si kolejnej z upraszczajcych programowanie w Javie strategii Springa: programowaniu deklaracyjnemu z uyciem aspektów. 1.1.3.
Stosujemy aspekty
DI pozwala na lune wizanie ze sob komponentów oprogramowania. Natomiast programowanie aspektowe umoliwia zgromadzenie w komponentach moliwych do ponownego wykorzystania rozwiza, których uycie jest rozproszone po caej aplikacji. Programowanie aspektowe jest czsto definiowane jako technika wspierajca izolowanie dziedzin dziaania w systemie oprogramowania. Systemy s zbudowane z pewnej liczby komponentów; kady jest odpowiedzialny za okrelony obszar dziaania. Czsto komponenty odpowiadaj dodatkowo za dziaania, które nie nale do ich gównej funkcji. Usugi systemowe, takie jak logowanie, zarzdzanie transakcjami i bezpieczestwo, czsto znajduj sposób, by pojawi si w komponentach, które przede wszystkim odpowiadaj za zupenie inne dziaania. Takie usugi systemowe czsto bywaj okrelane jako zagadnienia przekrojowe, poniewa maj tendencj do pojawiania si w wielu komponentach w przekroju systemu. Rozproszenie takich zagadnie po wielu komponentach wprowadza do naszego kodu dwa poziomy zoonoci: Q
Q
Kod implementujcy zagadnienia ogólnosystemowe jest powielany w wielu komponentach. To znaczy, e chcc zmieni obsug tych zagadnie, musimy modyfikowa wiele komponentów. Nawet gdybymy wydzielili problem do osobnego moduu, tak e wpyw na pozostae komponenty ograniczaby si do uycia pojedynczego wywoania metody, to wywoanie jest powielone w wielu miejscach. Nasze komponenty s zamiecone kodem, który nie jest zwizany z ich gówn funkcj. Metoda dodajca wpis do ksiki adresowej powinna zajmowa si wycznie dodawaniem adresu, a nie tym, czy odbywa si to w sposób bezpieczny lub transakcyjny.
Na rysunku 1.2 przedstawiono t zoono . Obiekty biznesowe po lewej s zbyt gboko zaangaowane w dziaanie usug systemowych. Nie tylko kady obiekt „wie”, e jego dziaanie jest rejestrowane, zabezpieczane i realizowane w sposób transakcyjny, lecz take kady obiekt sam odpowiada za realizowanie tych usug.
30
ROZDZIA 1. Zrywamy si do dziaania
Rysunek 1.2. Wywoania systemowych usug, dotyczcych dziedzin takich jak logowanie i bezpiecze stwo, czsto s rozproszone po moduach, w których usugi te nie stanowi gównej funkcji
AOP umoliwia umieszczenie takich usug w osobnych moduach i stosowanie ich w sposób deklaratywny dla komponentów, które tego potrzebuj. Skutkuje to tworzeniem komponentów o bardziej zwartej budowie i dziaaniu skoncentrowanym na waciwych sobie zadaniach, z zupenym lekcewaeniem potrzebnych usug systemowych. W skrócie, aspekty pozwalaj, by POJO pozostay proste. Moe pomóc mylenie o aspektach jako o kocach okrywajcych wiele komponentów w aplikacji, jak pokazano na rysunku 1.3. Rdze aplikacji skada si z moduów implementujcych funkcje biznesowe. Dziki AOP moemy nastpnie okry nasz rdze aplikacji warstwami realizujcymi usugi systemowe. Warstwy te mona naoy na nasz aplikacj za pomoc deklaracji w sposób elastyczny i w dodatku niewidoczny dla rdzenia aplikacji. Jest to potna koncepcja. Pozwala ochroni przed zamieceniem rdzenia aplikacji, realizujcego logik biznesow, sprawami bezpieczestwa, obsugi transakcji czy te logowania.
Rysunek 1.3. Dziki uyciu AOP moemy okry warstwami usug systemowych komponenty, które tych usug potrzebuj. To pozwala w komponentach aplikacji skupi si na specyficznej dla nich logice biznesowej
By zademonstrowa sposób stosowania aspektów w Springu, wró my do przykadu z rycerzem, dodajc do mieszanki prosty aspekt.
1.1.
31
Upraszczamy programowanie w Javie AOP
W DZIAANIU
Wszystkie informacje, jakie ktokolwiek posiada na temat rycerzy, dotary do nas dziki sawieniu ich czynów w pieniach przez uzdolnionych muzycznie gawdziarzy, zwanym minstrelami. Przyjmijmy, e wyjcia na misje i powroty z nich naszego dzielnego rycerza chcemy rejestrowa z uyciem usug wiadczonych przez minstrela. Poniej na listingu 1.8 pokazano klas Minstrel, której moglibymy uy . Listing 1.8. Minstrel jest muzycznie uzdolnionym systemem logowania z czasów redniowiecza
package com.springinaction.knights; Wywoanie public class Minstrel{ przed wyruszeniem na misj public void singBeforeQuest(){ System.out.println("Tra la la; Jaki rycerz jest dzielny!"); } Wywoanie po powrocie z misji public void singAfterQuest(){ System.out.println( "Hip hip hura; Dzielny rycerz wypeni misj!"); }
}
Jak widzimy, Minstrel jest prost klas z dwiema metodami. Metoda singBeforeQuest() jest przeznaczona do wywoywania przed podjciem si misji przez rycerza. Z kolei metoda singAfterQuest() powinna by wywoana po tym, jak rycerz wypeni misj. Powinno by atwo doda t klas do naszego kodu. Poczymy zatem niezbdne przystosowania w klasie BraveKnight, umoliwiajce korzystanie z klasy Minstrel. Pierwsze podejcie pokazano na listingu 1.9. Listing 1.9. Klasa BraveKnight, która musi wywoywa metody klasy Minstrel
package com.springinaction.knights; public class BraveKnight implements Knight{ private Quest quest; private Minstrel minstrel; public BraveKnight(Quest quest, Minstrel minstrel){ this.quest=quest; this.minstrel=minstrel; } public voidembarkOnQuest()throwsQuestException{ minstrel.singBeforeQuest(); quest.embark(); minstrel.singAfterQuest(); }
Czy rycerz powinien zajmowa si zarzdzaniem swoim minstrelem?
}
To powinno dziaa . Ale co tu wyglda na nieprawidowe. Czy rzeczywicie do zakresu zainteresowa rycerza naley zarzdzanie jego minstrelem? Wydaje mi si, e minstrel powinien zajmowa si swoj robot, nie czekajc, a rycerz go o to poprosi. W kocu tak minstrel ma prac — piewa o dokonaniach rycerza. Czemu rycerz miaby mu o tym cigle przypomina ?
32
ROZDZIA 1. Zrywamy si do dziaania
Co wicej, poniewa rycerz nie wie nic o minstrelu, jestemy zmuszeni do wstrzyknicia kodu Minstrela do klasy BraveKnight. To nie tylko komplikuje kod klasy Brave ´Knight, lecz take wywouje we mnie refleksj, czy kiedykolwiek bdziemy chcieli rycerza, który nie ma minstrela. Co si stanie, jeli Minstrel bdzie mia warto null? Czy powinnimy wprowadzi jak logik sprawdzajc wystpienie wartoci null, by obsuy taki przypadek? Nasza prosta klasa BraveKnight zaczyna si stawa coraz bardziej skomplikowana, a bdzie jeszcze gorzej, gdy pojawi si potrzeba obsuenia scenariusza z wartoci Minstrel równ null. Lecz korzystajc z AOP, moemy zdeklarowa , e minstrel powinien piewa o misjach rycerza i zwolni rycerza z obowizku bezporedniej obsugi metod klasy Minstrel. Aby uczyni klas Minstrel aspektem, musimy tylko zadeklarowa ten fakt w jednym z plików konfiguracyjnych Springa. Oto uaktualniony plik knights.xml, uzupeniony o deklaracj klasy Minstrel jako aspektu. Listing 1.10. Deklarujemy komponent Minstrel jako aspekt
Deklarujemy komponent Minstrel
Definiujemy punkt przecicia
Deklarujemy porad before
Deklarujemy porad after
Korzystamy tu z konfiguracyjnej przestrzeni nazw aop w Springu, by zadeklarowa , e komponent Minstrel jest aspektem. Najpierw musimy zadeklarowa , e Minstrel jest
1.1.
Upraszczamy programowanie w Javie
33
komponentem. Nastpnie odwoujemy si do tego komponentu w elemencie
. Dalej definiujc aspekt, deklarujemy (korzystajc z elementu ), e przed wykonaniem metody embarkOnQuest() powinna zosta wywoana metoda sing ´BeforeQuest() klasy Minstrel. Jest to porada typu before. Deklarujemy take (za pomoc elementu ), e po wykonaniu metody embarkOnQuest() naley wywoa metod singAfterQuest(). To z kolei jest porada typu after. W obydwu przypadkach atrybut pointcut-ref odwouje si do punktu przecicia nazwanego embark. Ten punkt przecicia jest zdefiniowany we wczeniejszym elemencie , z atrybutem expression o wartoci wskazujcej, w którym miejscu naley zastosowa si do porady. Skadnia wyrae pochodzi z wyrae punktów przecicia w jzyku AspectJ. Nie powinnimy si teraz martwi brakiem znajomoci jzyka AspectJ, w tym szczegóami zapisu wyrae punktów przecicia. Póniej, w rozdziale 4., powiemy wicej na temat AOP w Springu. Na chwil obecn wystarczy wiedzie , e polecilimy Springowi, by wywoywa metody klasy Minstrel, singBeforeQuest() oraz singAfterQuest(), odpowiednio przed podjciem si i po podjciu si przez dzielnego rycerza wykonania misji. I to ju wszystko, czego potrzeba! Za pomoc ociupinki XML przeksztacilimy klas Minstrel do aspektu w Springu. Nie martw si, Czytelniku, jeli nie widzisz w tym jeszcze wiele sensu. Wiele powinny wyjani przykady AOP w Springu z rozdziau 4. (a bdzie ich sporo). Na razie warto zapamita z tego przykadu dwie wane sprawy. Po pierwsze, Minstrel nadal jest POJO — nic w nim nie wskazuje, e bdzie uywany jako aspekt. By sta si aspektem, wystarczyo zadeklarowa w kontekcie Springa, e nim bdzie. Po drugie i najwaniejsze, klasa BraveKnight moe korzysta z usug klasy Minstrel, nie muszc ich wprost wywoywa . Waciwie BraveKnight pozostaje zupenie niewiadomy, e Minstrel istnieje. Powinnimy wskaza take, e pomimo uycia odrobiny magii Springa, by przeksztaci klas Minstrel w aspekt, najpierw zostaa ona zadeklarowana jako . Chodzi o to, e moemy zrobi z aspektami w Springu to wszystko, co z kadym innym rodzajem komponentów, na przykad uy ich do wstrzykiwania zalenoci. Uycie aspektów do piewania o rycerzach moe by zabawne. Lecz AOP w Springu nadaje si do znacznie bardziej praktycznych zastosowa. Jak si przekonamy póniej, programowanie aspektowe moemy wykorzysta do zapewnienia usug takich jak transakcje deklaracyjne (rozdzia 6.) i bezpieczestwo (rozdzia 9.). Lecz w tej chwili spójrzmy na jeszcze jeden ze sposobów, w jaki Spring upraszcza programowanie w Javie. 1.1.4.
Ograniczamy stosowanie kodu szablonowego dziki wzorcom
Czy zdarzyo si kiedy, e po napisaniu fragmentu kodu czue si, Czytelniku, jakby ju wczeniej pisa taki sam kod? To nie déjà vu, mój przyjacielu. Zdarzaj si takie fragmenty kodu (zwane kodem szablonowym), które musimy czsto pisa raz za razem w celu realizacji popularnych i skdind prostych zada. Niestety, wiele jest miejsc, w których API Javy wymaga nieco takiego cigle powtarzanego kodu. Czstym przykadem kodu szablonowego jest uycie JDBC do pobrania informacji z bazy danych. Jeli kiedykolwiek pracowae z JDBC, to prawdopodobnie pisae co podobnego do poniszego przykadu zaprezentowanego na listingu 1.11.
34
ROZDZIA 1. Zrywamy si do dziaania
Listing 1.11. Wiele elementów Java API, na przykad JDBC, wymaga uycia sporej iloci kodu szablonowego
public Employee getEmployeeById(longid){ Connection conn=null; PreparedStatement stmt=null; ResultSetrs=null; try { conn =dataSource.getConnection(); stmt =conn.prepareStatement( "select id,firstname,lastname,salaryfrom"+ "employee whereid=?"); Wybieramy stmt.setLong(1,id); pracownika rs =stmt.executeQuery(); Employe eemployee=null; if (rs.next()){ Tworzymy obiekt z danych employee=newEmployee(); employee.setId(rs.getLong("id")); employee.setFirstName(rs.getString("firstname")); employee.setLastName(rs.getString("lastname")); employee.setSalary(rs.getBigDecimal("salary")); } returnemployee; Jak czynno naley wykona w tym miejscu? } catch(SQLException e){ } finally{ if(rs!=null){ Sprztamy baagan try { rs.close(); } catch(SQLException e){} } if(stmt!=null){ try { stmt.close(); } catch(SQLExceptione){} } if(conn!=null){ try { conn.close(); } catch(SQLExceptione){} } } return null; }
Jak widzimy, ten kod obsugujcy JDBC wysya do bazy danych zapytanie o nazwisko i wynagrodzenie pracownika. Lecz zao si, e trzeba byo bardzo dokadnie si przyjrze , by to dostrzec. To dlatego, e may fragment kodu, który odpowiada za zapytanie o pracownika, jest zagrzebany pod stosem operacji zwizanych z „ceremoniaem” JDBC. Najpierw musimy utworzy poczenie, nastpnie wyraenie i w kocu moemy wyko-
1.1.
Upraszczamy programowanie w Javie
35
na samo zapytanie, by uzyska wyniki. Dodatkowo, by unikn gniewu JDBC, musimy obsuy wyjtek SQLException, mimo e nie jestemy w stanie wiele zdziaa w razie zgoszenia wyjtku. Na koniec, po wykonaniu wszystkich czynnoci musimy posprzta , zamykajc poczenie, wyraenie oraz zbiór wynikowy. To take moe wywoa gniew JDBC. Zatem tutaj take musimy obsugiwa wyjtek SQLException. Najbardziej charakterystyczny w kodzie na listingu 1.11 jest fakt, e wikszo tego kodu musimy powtarza dla prawie kadej operacji w JDBC. Tylko niewielki fragment ma cokolwiek wspólnego z zapytaniem o dane pracownika, a wikszo jest kodem szablonowym JDBC. A przecie JDBC nie ma wycznoci na stosowanie kodów szablonowych. Wiele czynnoci wymaga podobnego kodu szablonowego. JMS, JNDI czy te korzystanie z usug REST czsto wymaga sporej iloci czsto powtarzajcego si kodu. Spring stara si ogranicza uycie kodu szablonowego, przez przeniesienie go do zewntrznych szablonów. Szablon JdbcTemplate w Springu umoliwia wykonywanie operacji na bazie danych bez caego ceremoniau tradycyjnie wymaganego przez JDBC. Na przykad nalecy do Springa szablon SimpleJdbcTemplate (specjalizacja szablonu JdbcTemplate, która korzysta z nowych moliwoci Javy 5) umoliwia przepisanie metody getEmployeeById() w sposób pozwalajcy skoncentrowa si na zadaniu pobierania danych pracownika, zamiast obsugiwa dania API JDBC. Poniej na listingu 1.12 pokazano, jak taka poprawiona metoda getEmployeeById() mogaby wyglda . Listing 1.12. Szablony pozwalaj skoncentrowa si na gównym zadaniu podczas pisania kodu
public Employee getEmployeeById(long id){ return jdbcTemplate.queryForObject( Zapytanie SQL "select id,firstname,lastname,salary" + "from employee where id=?", new RowMapper(){ public Employee mapRow(ResultSet rs, int rowNum)throws SQLException{ Odwzorowujemy Employee employee=newEmployee(); wyniki na obiekt employee.setId(rs.getLong("id")); employee.setFirstName(rs.getString("firstname")); employee.setLastName(rs.getString("lastname")); employee.setSalary(rs.getBigDecimal("salary")); return employee; } }, Przekazujemy parametr zapytania id); }
Jak widzimy, nowa wersja metody getEmployeById() jest znacznie prostsza i skoncentrowana na zadaniu pobrania z bazy danych informacji o pracowniku. Naleca do szablonu metoda queryForObject() otrzymuje zapytanie w jzyku SQL, obiekt RowMapper (na potrzeby odwzorowania danych zbioru do obiektu domeny) oraz zero lub wicej parametrów zapytania. Tym, czego ju nie widzimy w metodzie getEmployeById(), bdzie cay kod szablonowy JDBC, który znajdowa si tam wczeniej. Kod ten jest w caoci realizowany wewntrz szablonu.
36
ROZDZIA 1. Zrywamy si do dziaania
Pokazalimy, w jaki sposób Spring radzi sobie ze zmniejszaniem zoonoci programowania w Javie dziki programowaniu opartemu na POJO, wstrzykiwaniu zalenoci, AOP oraz wzorcom. Przy okazji pokazalimy take sposób konfiguracji komponentów i aspektów za pomoc plików XML. Lecz w jaki sposób odbywa si adowanie tych plików? I do czego s one adowane? Przyjrzyjmy si kontenerowi Springa, miejscu, gdzie znajduj si komponenty wchodzce w skad naszej aplikacji.
1.2.
Kontener dla naszych komponentów Obiekty aplikacji napisanej z uyciem Springa znajdowa si bd wewntrz kontenera Springa. Jak pokazano na rysunku 1.4, kontener bdzie tworzy obiekty, powizania midzy nimi, konfigurowa je i zarzdza caym ich cyklem ycia „od koyski a po grób” (czy w tym przypadku raczej od operatora new a do metody finalize()).
Rysunek 1.4. Aplikacja w Springu tworzy obiekty i powizania midzy nimi oraz przechowuje obiekty wewntrz kontenera Springa
W nastpnym rozdziale zobaczymy, jak skonfigurowa Springa, by wiedzia, jakie obiekty utworzy , skonfigurowa i powiza . W pierwszej kolejnoci wane jest, bymy poznali kontener, w jakim znajduj si nasze obiekty. Zrozumienie dziaania kontenera pozwoli nam uchwyci sposób, w jaki bd zarzdzane nasze obiekty. Kontener jest podstaw frameworka Spring. Kontener Springa korzysta z wstrzykiwania zalenoci do zarzdzania komponentami tworzcymi aplikacj. Midzy innymi tworzy powizania midzy wspópracujcymi komponentami. Jako takie, obiekty te s bardziej czytelne i atwiejsze do zrozumienia, nadaj si do wielokrotnego uycia i uatwiaj wykonywanie testów jednostkowych. Nie jestemy w Springu ograniczeni do tylko jednego typu kontenera. Spring posiada kilka implementacji kontenerów, które mona podzieli na dwie grupy. Fabryki komponentów (zdefiniowane przez interfejs org.springframework.beans.factory.BeanFactory) s najprostszymi kontenerami, zapewniajcymi podstawowe wsparcie dla techniki DI. Konteksty aplikacji (zdefiniowane przez interfejs org.springframework.context.Appli ´cationContext) s rozwiniciem koncepcji fabryki komponentów, zapewniajc aplikacji dodatkowo usugi rodowiska, takie jak moliwo analizowania komunikatów tekstowych z plików waciwoci czy te przekazywania zdarze w aplikacji do zainteresowanych procesów nasuchujcych. Cho mona pracowa w Springu, korzystajc albo z fabryk komponentów, albo z kontekstów aplikacji, fabryki okazuj si czsto rozwizaniem zbyt niskopoziomowym
1.2.
Kontener dla naszych komponentów
37
dla wikszoci zastosowa. Dlatego konteksty aplikacji s rozwizaniem preferowanym. Skupimy si na pracy z nimi, nie marnujc wicej czasu na rozmow o fabrykach komponentów. 1.2.1.
Pracujemy z kontekstem aplikacji
Spring posiada kilka odmian kontekstu aplikacji. Trzy, które prawdopodobnie najczciej napotkasz, to: Q
Q
Q
ClassPathXmlApplicationContext — aduje definicj kontekstu z pliku XML,
znajdujcego si w ciece klas; traktuje pliki z definicjami kontekstu jako zasoby w ciece do klas. FileSystemXmlApplicationContext — aduje definicj kontekstu z pliku XML znajdujcego si w systemie plików. XmlWebApplicationContext — aduje definicj kontekstu z pliku XML znajdujcego si wewntrz aplikacji internetowej.
Wicej o kontekcie XmlWebApplicationContext powiemy w rozdziale 7., podczas dyskusji o aplikacjach internetowych w Springu. Na razie zaadujmy po prostu kontekst aplikacji z systemu plików, korzystajc z kontekstu FileSystemXmlApplicationContext, lub ze cieki do klas, korzystajc z kontekstu ClassPathXmlApplicationContext. adowanie kontekstu aplikacji z systemu plików lub cieki do klas odbywa si w podobny sposób do tego, jak adowalimy komponenty do fabryki. Na przykad, w nastpujcy sposób adujemy kontekst FileSystemXmlApplicationContext: ApplicationContext context = new FileSystemXmlApplicationContext("c:/foo.xml");
Podobnie adujemy kontekst z uyciem ClassPathXmlApplicationContext: ApplicationContext context = new ClassPathXmlApplicationContext("foo.xml");
Rónica midzy tymi dwoma sposobami polega na tym, e kontekst FileSystemXmlAppli ´cationContext oczekuje pliku foo.xml w okrelonej lokalizacji, podczas gdy kontekst ClassPathXmlApplicationContext szuka go gdziekolwiek w ciece do klas (wcznie z plikami JAR). Majc ju kontekst aplikacji, moemy pobra komponenty z kontenera Springa, wywoujc nalec do kontenera metod getBean(). Kiedy znamy ju podstawy tworzenia kontenera w Springu, przyjrzyjmy si bliej cyklowi ycia komponentu w kontenerze. 1.2.2.
Cykl ycia komponentu
W przypadku tradycyjnej aplikacji w Javie, cykl ycia komponentu jest prosty. Sowo kluczowe new powoduje utworzenie instancji komponentu (lub by moe jego deserializacj) i od tego momentu komponent jest gotów do dziaania. Odkd komponent nie jest ju w uyciu, jest on przekazywany do procesu oczyszczania pamici i w pewnym momencie trafia do „wielkiego kuba bitów na niebie”. Z kolei cykl ycia komponentu w kontenerze Springa jest bardziej skomplikowany. Wane jest zrozumienie cyklu ycia komponentu w Springu, poniewa moemy chcie
38
ROZDZIA 1. Zrywamy si do dziaania
skorzysta z niektórych oferowanych przez Springa moliwoci dostosowania sposobu tworzenia komponentu. Na rysunku 1.5 pokazano pocztek cyklu ycia dla typowego komponentu, adowanego do kontekstu aplikacji w Springu.
Rysunek 1.5. Komponent w kontenerze Springa przechodzi pewn liczb etapów pomidzy utworzeniem i likwidacj. Kady etap daje moliwo modyfikacji sposobu zarzdzania komponentem w Springu
Jak widzimy, fabryka komponentów wykonuje wiele kroków konfiguracji, zanim komponent bdzie gotowy do uycia. Ujmujc zawarto rysunku 1.5 bardziej szczegóowo: 1. Spring tworzy instancj komponentu. 2. Spring wstrzykuje do waciwoci komponentu wartoci i referencje do innych komponentów. 3. Jeli komponent implementuje interfejs BeanNameAware, Spring przekazuje metodzie setBeanName() jako parametr nazw komponentu. 4. Jeli komponent implementuje interfejs BeanFactoryAware, Spring wywouje metod setBeanFactory(), z biec fabryk komponentów jako parametrem. 5. Jeli implementuje interfejs ApplicationContextAware, Spring wywoa metod setApplicationContext(), przekazujc jej jako parametr referencj do zawierajcego ten komponent kontekstu aplikacji. 6. Jeli które z komponentów implementuj interfejs BeanPostProcesor, Spring wywoa ich metod postProcessBeforeInitialization(). 7. Jeli jakie komponenty implementuj interfejs InitializingBean, Spring wywouje ich metod afterPropertiesSet(). Podobnie, jeli komponent posiada deklaracj init-method, wówczas zostanie wywoana wskazana metoda inicjujca. 8. Jeli istniej komponenty, które implementuj interfejs BeanPostProcessor, Spring wywoa ich metod postProcessAfterInitialization(). 9. Dochodzc do tego punktu, komponent jest gotów do uycia przez aplikacj i pozostanie w kontekcie aplikacji, dopóki ten nie zostanie zlikwidowany.
1.3.
Podziwiamy krajobraz Springa
39
10. Jeli które z komponentów implementuj interfejs DisposableBean, Spring wywoa ich metod destroy(). Podobnie, jeli jaki komponent posiada deklaracj destroy-method, wówczas zostanie wywoana wskazana metoda. Teraz ju wiemy, jak utworzy i zaadowa kontener w Springu. Lecz pusty kontener sam z siebie nie stanowi wielkiej wartoci, a nie bdzie niczego zawiera, zanim sami tam czego nie umiecimy. Aby osign korzy z techniki DI w Springu, musimy dokona wizania obiektów naszej aplikacji wewntrz kontenera. Bardziej szczegóowo do kwestii wizania komponentów podejdziemy w rozdziale 2. Lecz najpierw obejrzyjmy krajobraz nowoczesnego Springa — przekonujc si, w jaki sposób jest skonstruowane rodowisko i co maj do zaoferowania jego najnowsze wersje.
1.3.
Podziwiamy krajobraz Springa Jak widzielimy, dziaanie frameworka Spring koncentruje si na upraszczaniu tworzenia oprogramowania klasy enterprise w Javie dziki wstrzykiwaniu zalenoci, programowaniu aspektowemu i eliminacji kodu szablonowego. Nawet gdyby na tym koczya si korzy z uycia Springa, byoby warto. Lecz Spring ma do zaoferowania wicej, ni wida na pierwszy rzut oka. Sam Spring Framework oferuje kilka sposobów na uatwienie programowania, lecz za frameworkiem stoi jeszcze potny ekosystem projektów bazujcych na nim jako podou, rozcigajc moliwoci Springa na takie obszary, jak usugi sieciowe, OSGi, Flash, a nawet .Net. Rozómy frameworka Spring na elementy, by przekona si, co ma do zaoferowania. Nastpnie rozszerzymy horyzonty, dokonujc przegldu wielkiej rodziny projektów zwizanych ze Springiem.
1.3.1.
Moduy Springa
Framework Spring jest zbudowany z wielu oddzielnych moduów. Rozpakowujc pobran dystrybucj frameworka, zauwaymy 20 rónych plików JAR w katalogu dist, jak pokazano na rysunku 1.6. Te 20 plików mona podzieli na sze rónych kategorii, jak pokazano na rysunku 1.7. Jako cao moduy te zaspokajaj wszystkie potrzeby programisty piszcego aplikacje klasy enterprise. Lecz nasze aplikacje nie musz w caoci bazowa na frameworku Spring. Moemy swobodnie dobiera moduy odpowiednie dla naszej aplikacji, korzystajc take z innych róde, gdy Spring okae si niewystarczajcy. W Springu mamy nawet do dyspozycji punkty integracji z kilkoma innymi frameworkami i bibliotekami, wic nie bdziemy musieli sami ich pisa . Przyjrzyjmy si kolejno kademu z moduów, tworzc sobie stopniowo caociowy obraz frameworka Spring. PODSTAWOWY KONTENER SPRINGA
Centralnym elementem frameworka Spring jest kontener, który kontroluje sposób tworzenia i konfiguracji komponentów w aplikacji stworzonej na bazie tego frameworka oraz zarzdzania tymi komponentami. W tym module znajdziemy fabryk komponentów,
40
ROZDZIA 1. Zrywamy si do dziaania
Rysunek 1.6. Pliki JAR nalece do dystrybucji frameworka Spring
Rysunek 1.7. Framework Spring skada si z szeciu dobrze zdefiniowanych moduów
czyli element frameworka realizujcy wstrzykiwanie zalenoci. Mamy te kilka implementacji kontekstu aplikacji w Springu, bdcych rozszerzeniem fabryki komponentów, z których kada umoliwia inny sposób konfiguracji Springa. Poza fabryk komponentów i kontekstami aplikacji modu ten zawiera wiele usug dla aplikacji biznesowych, jak poczta elektroniczna, dostp przez JNDI, integracja EJB i szeregowanie zada.
1.3.
Podziwiamy krajobraz Springa
41
Jak widzimy, wszystkie moduy Springa bazuj na podstawowym kontenerze. Klas tych oczywicie uyjemy, konfigurujc nasz aplikacj. Podstawowy modu bdziemy omawia w caej tej ksice, rozpoczynajc od rozdziau 2., w którym zagbimy si we wstrzykiwanie zalenoci w Springu. MODU AOP
W
SPRINGU
Spring posiada w module AOP szerokie wsparcie dla programowania aspektowego. Modu ten stanowi punkt wyjcia do tworzenia wasnych aspektów dla naszej aplikacji w Springu. Podobnie jak DI, AOP pozwala na lune wizanie obiektów aplikacji. Lecz dziki AOP zagadnienia rozproszone po caej aplikacji (jak obsuga transakcji i bezpieczestwa) zostaj oddzielone od obiektów, które z nich korzystaj. W obsug AOP w Springu zagbimy si w rozdziale 4. DOSTP DO DANYCH I INTEGRACJA
Praca z JDBC czsto skutkuje potrzeb uycia sporej iloci kodu szablonowego do nawizania poczenia, utworzenia wyraenia, obsugi zbioru wynikowego i na koniec — zamknicia poczenia. Modu Springa obsugujcy JDBC oraz obiekty dostpu do danych (ang. Data Access Objects, DAO) wydobywa z aplikacji kod szablonowy, pozwalajc na tworzenie czystego i prostego kodu wspópracujcego z bazami danych, jednoczenie chronic przed problemami skutkujcymi niepoprawnym zamkniciem lub nawet uszkodzeniem zasobów bazodanowych. Modu ten obudowuje take komunikaty o bdach pochodzce od wielu serwerów baz danych warstw wyjtków posiadajcych znacznie bardziej zrozumiae komunikaty. Ju nigdy wicej rozszyfrowywania tajnych lub zastrzeonych komunikatów o bdach SQL! Dla tych, którzy wol uywa narzdzi odwzorowywania obiektowo-relacyjnego (ang. object-relational mapping, ORM) zamiast bezporedniego JDBC, Spring udostpnia modu ORM. Obsuga ORM w Springu jest oparta na obsudze DAO, zapewniajc porczny sposób na zbudowanie DAO dla wielu rozwiza ORM. Spring nie próbuje implementowa jakiego wasnego rozwizania ORM, lecz posiada przycza dla wielu popularnych rodowisk ORM, w tym Hibernate, Java Persistance API, Java Data Objects czy iBATIS SQL Maps. Zarzdzanie transakcjami w Springu obsuguje kade z tych rodowisk ORM, w podobny sposób jak JDBC. Przekonamy si, w jaki sposób oparta na szablonach abstrakcja JDBC w Springu pozwala znacznie uproci kod korzystajcy z JDBC, analizujc dostp do danych w Springu, opisany w rozdziale 5. Modu ten zawiera take abstrakcj usugi wiadomoci Javy (ang. Java Message Service, JMS), pozwalajcej na asynchroniczn integracj z innymi aplikacjami za pomoc wiadomoci. Poczwszy od wersji 3.0 Springa, w module tym znajdziemy take funkcje odwzorowywania obiektów do XML, które pierwotnie byy czci projektu Spring Web Services. Dodatkowo, modu ten korzysta z moduu AOP, by udostpni obiektom w aplikacji usugi zarzdzania transakcjami. Szczegóowo obsudze transakcji w Springu przyjrzymy si w rozdziale 6.
42
ROZDZIA 1. Zrywamy si do dziaania
USUGI SIECIOWE I ZDALNE
Paradygmat model-widok-kontroler (ang. Model-View-Controller, MVC) jest powszechnie przyjtym podejciem do konstruowania aplikacji internetowych, w których interfejs uytkownika jest rozdzielony od logiki aplikacji. W Javie nie brakuje frameworków MVC, wród których mamy Apache Struts, JSF, Web Work czy Tapestry, by wymieni jedynie najbardziej popularne rozwizania. Mimo e Spring integruje si z wieloma popularnymi rodowiskami MVC, jego modu usug sieciowych i zdalnych zawiera nieze rodowisko MVC, które wspiera Springow technik lunego wizania w webowej warstwie aplikacji. rodowisko to funkcjonuje w dwóch postaciach: bazujcej na serwletach dla tradycyjnych aplikacji internetowych i bazujcej na portletach dla programistów preferujcych Java portlet API. Poza aplikacjami internetowymi, z którymi bdzie mia bezporednio do czynienia uytkownik, modu ten posiada kilka opcji usug zdalnych, na potrzeby konstruowania aplikacji, które bd wspópracowa z innymi aplikacjami. Obsuga usug zdalnych w Springu obejmuje rozwizanie takie jak zdalne wywoywanie metod (ang. Remote Method Invocation, RMI), Hessian, Burlap, JAX-WS, a take nalecy do Springa mechanizm HTTP invoker. rodowisku MVC Springa przyjrzymy si w rozdziale 7. Póniej, w rozdziale 10., poznamy szczegóy usug zdalnych w Springu. TESTOWANIE
Dostrzegajc wano testów pisanych przez programist, w Springu zawarto modu dedykowany do testowania aplikacji utworzonych w tym rodowisku. W tym module znajdziemy kolekcj imitacji implementowanych obiektów na potrzeby tworzenia przez programistów testów moduów, obsugujcych JNDI, serwlety i portlety. Na potrzeby testowania etapu integracji modu ten zawiera obsug adowania kolekcji komponentów do kontekstu aplikacji w Springu i pracy z komponentami w tym kontekcie. Po raz pierwszy zasmakujemy moduu testowania Springa w rozdziale 4. Nastpnie, w rozdziaach 5. i 6., rozszerzymy nasz wiedz o testowanie w Springu dostpu do danych i transakcji. 1.3.2.
Rodzina projektów wokó Springa
Spring to wicej, ni wida na pierwszy rzut oka. Waciwie to znacznie wicej ni dostpny do pobrania z internetu pakiet instalacyjny frameworka Spring. Gdybymy zatrzymali si na samych tylko podstawach frameworka Spring, przegapilibymy bogactwo potencjau, jaki posiada wielka rodzina otaczajcych go projektów. Rodzina ta zawiera wiele rodowisk uruchomieniowych i bibliotek, które bazuj na rdzeniu frameworka Spring lub na sobie nawzajem. Wzite razem, projekty te obejmuj modelem programowania Springa prawie kad paszczyzn programowania w Javie. Zajoby wiele tomów, by opisa wszystko, co ma do zaoferowania caa rodzina projektów otaczajcych Springa, i wikszo z tego wykracza poza zakres tej ksiki. Lecz zerkniemy na niektórych przedstawicieli tej wielkiej rodziny. Za na razie oto przedsmak tego wszystkiego, co ley poza rdzeniem frameworka Spring.
1.3.
Podziwiamy krajobraz Springa
43
SPRING WEB FLOW
Spring Web Flow bazuje na nalecym do frameworka Spring module MVC, by umoliwi konstruowanie konwersacyjnych, bazujcych na przepywie informacji aplikacji internetowych prowadzcych uytkownika do celu (pomylmy o kreatorach lub koszykach sklepowych). Powiemy wicej o Spring Web Flow w rozdziale 8., a jeszcze wicej o tym projekcie mona si dowiedzie z jego strony domowej pod adresem http://www. springsource.org/webflow. SPRING WEB SERVICES
Cho rdze frameworka Spring pozwala na deklaracyjn obsug publikowania komponentów Springa jako usug sieciowych, usugi te oparte s na niewtpliwie gorszym pod wzgldem architektury modelu „kontrakt na kocu”. Kontrakt na usug jest ustalany na podstawie interfejsu implementowanego przez komponent. Spring Web Services korzysta z modelu „najpierw kontrakt”, w którym implementacje usug pisane s, by speni kontrakt na usugi. Nie bdziemy omawia w tej ksice projektu Spring-WS, zainteresowany nim czytelnik moe sign po wicej informacji na stron domow projektu pod adresem http://static.springsource.org/spring-ws/sites/2.0. SPRING SECURITY
Bezpieczestwo jest najwaniejszym aspektem dziaania wielu aplikacji. Projekt Spring Security, bazujcy w swej implementacji na module AOP Springa, umoliwia deklarowanie mechanizmów bezpieczestwa w aplikacjach opartych na Springu. Jak doda do aplikacji rozwizania projektu Spring Security, dowiemy si w rozdziale 9. Na potrzeby dalszych poszukiwa, pod adresem http://static.springsource.org/spring-security/site znajduje si strona domowa projektu Spring Security. SPRING INTEGRATION
Wiele aplikacji biznesowych musi wspópracowa z innymi aplikacjami biznesowymi. Projekt Spring Integration udostpnia implementacje wielu popularnych wzorców integracji realizowanych w deklaratywnym stylu Springa. Nie opisujemy w tej ksice projektu Spring Integration. Osobom zainteresowanym szczegóami tego projektu polecamy ksik Spring Integration in Action, któr napisali Mark Fisher, Jonas Partner, Marius Bogoevici i Iwein Fuld. Albo te wizyt na stronie domowej projektu, pod adresem http://www.springsource.org/spring-integration. SPRING BATCH
Kiedy zachodzi potrzeba wykonania hurtowo pewnych operacji na danych, nie do pobicia jest przetwarzanie wsadowe. Jeli aplikacja, któr zamierzasz pisa , bdzie przetwarzaa dane wsadowo, moesz oprze j na solidnym, korzystajcym z POJO modelu programowania w Springu, korzystajc z projektu Spring Batch. Projekt ten wykracza poza zakres niniejszej ksiki. Jednak mog Ci, Czytelniku, owieci Thierry Templier i Arnaud Cogoluègnes w ksice ich autorstwa, pod tytuem Spring Batch in Action. Moesz take nauczy si korzystania ze Spring Batch na stronie domowej projektu, pod adresem http://static.springsource.org/spring-batch.
44
ROZDZIA 1. Zrywamy si do dziaania
SPRING SOCIAL
Sieci spoecznociowe s coraz popularniejszym zagadnieniem w internecie i coraz wicej aplikacji zostaje wyposaonych w moliwo integracji z serwisami sieci spoecznociowych, takich jak Facebook lub Twitter. Jeli jest to tematyka leca w krgu Twoich zainteresowa, na pewno bdziesz chcia zapozna si z projektem Spring Social, czyli rozszerzeniem do Springa obsugujcym sieci spoecznociowe. Spring Social jest wzgldnie nowym projektem i nie zosta opisany w tej ksice. Moesz dowiedzie si o nim wicej pod adresem http://www.springsource.org/springsocial. SPRING MOBILE
Aplikacje mobilne s kolejnym wanym kierunkiem rozwoju oprogramowania. Smartfony i tablety przejmuj u wielu uytkowników pozycj preferowanych rozwiza klienckich. Spring Mobile jest nowym rozszerzeniem dla Springa, wspierajcym programowanie mobilnych aplikacji internetowych. Spokrewniony ze Spring Mobile jest projekt Spring Android. To nowy projekt, powstay w cigu ostatniego miesica przed momentem pisania tych sów. Jego celem jest przeniesienie prostoty osignitej przez rodowisko Spring do programowania natywnych aplikacji dla urzdze z systemem Android. Na pocztkowym etapie rozwoju projekt ten udostpnia jedynie wersj wzorca RestTemplate (wicej o RestTemplate w rozdziale 11.) dziaajc w aplikacjach dla Androida. Ponownie, projekty te s nowe i wykraczaj poza zakres ksiki Spring w Akcji, lecz mona dowiedzie si o nich wicej pod adresami http://www.springsource.org/springmobile oraz http://www.springsource.org/spring-android. SPRING DYNAMIC MODULES
Projekt Spring Dynamic Modules (Spring-DM) czy w sobie deklaracyjne wstrzykiwanie zalenoci Springa z dynamiczn moduowoci inicjatywy OSGi. Korzystajc ze Spring-DM, mona konstruowa aplikacje zbudowane z wielu oddzielnych, bardzo zwartych, luno powizanych moduów, deklarujcych, e s dostawcami lub konsumentami usug w rodowisku OSGi. Naley zauway , e ze wzgldu na jego ogromny wpyw na wiat uytkowników OSGi, model Spring-DM dla deklarowanych usug OSGi zosta formalnie wczony do specyfikacji OSGi jako OSGi Blueprint Container. Dodatkowo spoeczno SpringSource wczya Spring-DM do projektu Eclipse jako cz rodziny projektów OSGi o nazwie Gemini, std jest take znany pod nazw Gemini Blueprint. SPRING LDAP
Poza wstrzykiwaniem zalenoci i AOP nastpn popularn technik stosowan w frameworku Spring jest tworzenie abstrakcji opartych na szablonach wokó niepotrzebnie skomplikowanych operacji, takich jak zapytania w JDBC czy przekazywanie komunikatów w JMS. Projekt Spring LDAP przynosi ze sob dostp do LDAP w opartym na szablonach stylu Springa. Dziki temu mona wyeliminowa kod szablonowy, powszechnie stosowany w operacjach LDAP. Wicej informacji na temat projektu Spring LDAP mona znale pod adresem http://www.springsource.org/ldap.
1.3.
Podziwiamy krajobraz Springa
45
SPRING RICH CLIENT
Aplikacje internetowe zdaj si odbiera tradycyjnym aplikacjom zainteresowanie uytkowników. Lecz jeli nadal naleysz do nielicznej grupy programistów tworzcych aplikacje korzystajce z biblioteki Swing, zainteresuje Ci projekt Spring Rich Client, tworzcy zestaw narzdzi dla programistów bogatych aplikacji, który piszcym w Swingu daje do rk potg Springa. SPRING.NET
Nie musisz porzuca wstrzykiwania zalenoci i programowania aspektowego, gdy przyjdzie Ci si zmierzy z projektem na platformie .NET. Spring.NET przenosi na platform .NET znane lune wizanie i moliwoci aspektowe Springa. Dodatkowo, poza podstawami, technikami takimi jak DI czy AOP, projekt Spring.Net posiada kilka moduów uatwiajcych programowanie na platformie .NET, w tym moduy do pracy z ADO.NET, NHibernate, ASP.NET oraz MSMQ. Wicej na temat projektu Spring.NET mona si dowiedzie , odwiedzajc stron http://www.springframework.net. SPRING-FLEX
Flex i AIR firmy Adobe s jednymi z najpotniejszych narzdzi do tworzenia bogatych aplikacji internetowych. Gdy pojawia si potrzeba interakcji takich bogatych interfejsów uytkownika z kodem Javy po stronie serwera, mog one korzysta z technologii usug zdalnych i przesyania komunikatów znanej jako BlazeDS. Pakiet integracji SpringFlex umoliwia komunikacj za pomoc BlazeDS aplikacji napisanych z uyciem Flex lub AIR z beanami Springa po stronie serwera. Pakiet ten zawiera take dodatek dla Spring Roo umoliwiajcy byskawiczne konstruowanie aplikacji z uyciem Flex. Swoje poznawanie projektu SpringFlex mona rozpocz pod adresem http://www. springsource.org/spring-flex. Interesujcy moe si okaza take projekt Spring ActionScript, opisany pod adresem http://www.springactionscript.org, który wiele z zalet frameworka Spring udostpnia programujcym w ActionScript. SPRING ROO
Podczas gdy coraz wiksza liczba programistów opiera si w swojej pracy na frameworku Spring, wokó Springa i pokrewnych rodowisk uruchomieniowych pojawi si zbiór wspólnych poj i dobrych praktyk. Jednoczenie popularno zaczy zyskiwa frameworki takie jak Ruby on Rails czy Grails, oparte na skryptowym modelu programowania, uatwiajcym zadanie konstruowania aplikacji. Projekt Spring Roo udostpnia interaktywne rodowisko narzdziowe, pozwalajce na byskawiczne tworzenie aplikacji w Springu, czc w jednym miejscu dobre praktyki odkryte przez ostatnich kilka lat. Tym, co wyrónia Roo na tle innych rodowisk byskawicznego tworzenia aplikacji, jest fakt, e w wyniku otrzymujemy kod w Javie z uyciem frameworka Spring. Na wyjciu dostajemy solidn aplikacj w Springu, nie jakie osobne rodowisko napisane w jzyku egzotycznym dla wikszoci twórców aplikacji biznesowych. Wicej informacji na temat projektu Spring Roo mona znale pod adresem http://www.springsource.org/roo.
46
ROZDZIA 1. Zrywamy si do dziaania
ROZSZERZENIA SPRINGA
Poza wszystkimi dotychczas opisanymi projektami istnieje take zbiór rozszerze Springa tworzony przez spoeczno . Opisano je na stronie http://www.springsource.org/extensions. Oto kilka znajdujcych si tam przysmaków: Q Q Q Q Q
1.4.
Implementacja Springa dla jzyka Python. Przechowywanie wielkich obiektów binarnych (ang. Binary Large OBject, BLOB). Nieulotno z uyciem db4o i CouchDB. Oparta na Springu biblioteka zarzdzania przebiegiem prac. Rozszerzenie moduu Spring Security o wspóprac z mechanizmami Kerberos i SAML.
Co nowego w Springu Miny prawie trzy lata od momentu napisania drugiego wydania tej ksiki1. W tym czasie wiele si wydarzyo. Ukazay si dwa kolejne wydania frameworka Spring, oba przynoszce ze sob nowe mechanizmy i ulepszenia suce atwiejszemu tworzeniu aplikacji. Take wiele z rodziny projektów otaczajcych framework Spring ulego znaczcym zmianom. Wiele z tych zmian opiszemy w tej ksice. Na razie jednak skrótowo zarysujemy nowoci we frameworku Spring.
1.4.1.
Co nowego w Springu 2.5?
W listopadzie 2007 roku zespó Springa wyda wersj 2.5 Spring Framework. Znaczc zmian w wersji 2.5 byo wprowadzenie w Springu programowania sterowanego adnotacjami. Wczeniej norm bya konfiguracja z uyciem plików XML. Lecz w wersji 2.5 Springa wprowadzono kilka sposobów, by za pomoc adnotacji znacznie ograniczy ilo potrzebnego w konfiguracji Springa kodu XML: Q
Q
Q
Q
Q
Wstrzykiwanie zalenoci sterowane adnotacjami (adnotacja @Autowired) i precyzyjne sterowanie automatycznym wizaniem (adnotacja @Qualifier). Obsuga adnotacji zgodnych ze specyfikacj JSR-250, wcznie z adnotacj @Resource dla wstrzykiwania zalenoci od nazwanego zasobu, a take adnotacjami @PostConstruct i @PreDestroy dla metod obsugi cyklu ycia. Automatyczne wykrywanie komponentów Springa wyposaonych w adnotacj @Component (lub jedn z kilku stereotypowych adnotacji). Zupenie nowy, sterowany adnotacjami model programowania Spring MVC, który wspaniale upraszcza programowanie aplikacji internetowych w Springu. Nowe rodowisko do testów integracyjnych, oparte na JUnit 4 i adnotacjach.
Chocia adnotacje byy wielkim przeomem w Springu 2.5, s jeszcze inne nowoci: Q
Q
1
Pena obsuga Javy 6 i Javy EE 5, w tym JDBC 4.0, JTA1.1, JavaMail 1.4 oraz JAX-WS 2.0. Nowe wyraenie punktu przecicia z nazw komponentu, pozwalajce wplata aspekty do komponentów Springa przez wskazanie nazwy komponentu.
Wydanie ang. z 2007 r. — przyp. tum.
1.4.
Co nowego w Springu Q Q
Q
47
Wbudowana obsuga wplatania podczas adowania pochodzca z AspectJ. Nowe konfiguracyjne przestrzenie nazw w XML, w tym przestrze nazw context, pozwalajca na konfigurowanie szczegóów kontekstu aplikacji, oraz przestrze nazw jms, suca do konfiguracji komponentów sterowanych komunikatami. Obsuga nazwanych parametrów w szablonie SqlJdbcTemplate.
Podczas dalszej lektury tej ksiki zapoznamy si z wieloma z tych nowych funkcjonalnoci Springa. 1.4.2.
Co nowego w Springu 3.0?
Po wszystkich wspaniaociach dodanych w Springu 2.5 trudno sobie wyobrazi , co nowego mogoby si pojawi w kolejnej wersji. Wersja 3.0 przynosi jednak kolejne ulepszenia przez kontynuacj motywu sterowania adnotacjami oraz kilka nowych moliwoci: Q
Q
Q
Q Q
Q Q Q
Q
Kompleksowa obsuga REST w Spring MVC, w tym kontrolery Spring MVC, które prawidowo reaguj na adresy URL w stylu REST, odpowiadajc za pomoc XML, JSON, RSS lub w inny odpowiedni sposób. Nowej obsudze REST w Springu przyjrzymy si w rozdziale 11. Nowy jzyk wyrae, który wznosi wstrzykiwanie zalenoci w Springu na nowy poziom, umoliwiajc wstrzykiwanie wartoci pochodzcych z rónorodnych róde, w tym od innych beanów i z waciwoci systemowych. W jzyk wyrae Springa zagbimy si w nastpnym rozdziale. Nowe adnotacje dla Spring MVC, w tym @CookieValue oraz @Request-Header, pozwalajce wydobywa wartoci odpowiednio z plików cookie i nagówków da. Sposób uycia tych adnotacji poznamy w rozdziale 7., podczas omawiania Spring MVC. Nowa przestrze nazw w XML, uatwiajca konfiguracj Spring MVC. Obsuga deklaracyjnego sprawdzania poprawnoci zgodna z adnotacjami wedug JSR-303 (Bean Validation). Obsuga nowej specyfikacji wstrzykiwania zalenoci wedug JSR-330. Adnotacyjna deklaracja metod asynchronicznych i planowanych. Nowy, oparty na adnotacjach model konfiguracji, który pozwala na konfigurowanie Springa niemal zupenie bez uycia plików XML. Temu nowemu sposobowi konfiguracji przyjrzymy si w nastpnym rozdziale. Funkcjonalno odwzorowania obiektów na XML przeniesiona z projektu Spring Web Services do rdzenia frameworka Spring.
Niemal równie wane jak nowoci w wersji 3.0 Springa jest to, co si tam nie znalazo. Szczególnie wymagane jest obecnie uycie Javy 5, poniewa Java 1.4 przestaa by oficjalnie wspierana i nie bdzie wicej obsugiwana przez Springa. 1.4.3.
Co nowego w rodzinie projektów otaczajcych Springa?
Równolegle do rdzenia frameworka Spring, take wród projektów bazujcych na Springu wydarzyo si par nowych, ciekawych rzeczy. Nie ma tutaj do miejsca, by opisa zmiany w szczegóach, lecz jest kilka elementów, które uznaem za znaczce i warte, by o nich wspomnie :
48
ROZDZIA 1. Zrywamy si do dziaania
Q
Q
Q
Zostaa wydana wersja 2.0 Spring Web Flow, w której uproszczono schemat definicji przepywów, jeszcze bardziej uatwiajc konstruowanie konwersacyjnych aplikacji internetowych. Razem ze Spring Web Flow 2.0 pojawiy si Spring JavaScript i Spring Faces. Spring JavaScript jest bibliotek JavaScript, która pozwala na stopniowe rozszerzanie stron internetowych o dynamiczn zawarto . Spring Faces pozwala na uycie JSF jako technologii widoku wspópracujcej ze Spring MVC lub Spring Web Flow. Dawne rodowisko Acegi Security zostao cakowicie odnowione i wydane jako Spring Security 2.0. W tym nowym wcieleniu Spring Security otrzymao nowy schemat konfiguracji, który znaczco ogranicza zapotrzebowanie na XML podczas konfigurowania elementów bezpieczestwa w aplikacji.
Nawet podczas pisania tej ksiki ewolucja projektu Spring Security postpuje. Niedawno zostaa wydana wersja 3.0, która jeszcze bardziej upraszcza deklarowanie rozwiza sucych bezpieczestwu. Korzysta ona z nowego jzyka wyrae podczas deklarowania zagadnie bezpieczestwa. Jak widzimy, Spring jest aktywnym, cigle ewoluujcym projektem. Cigle pojawia si co nowego, co ma na celu uatwianie programowania aplikacji biznesowych.
1.5.
Podsumowanie Teraz powiniene ju, Czytelniku, mie nieze wyobraenie o tym, co Spring przynosi ze sob. Celem Springa jest uczynienie programowania aplikacji biznesowych atwiejszym i promowanie luno wizanego kodu. Fundamentem jest wstrzykiwanie zalenoci i AOP. W tym rozdziale uzyskalimy przedsmak wstrzykiwania zalenoci w Springu. DI jest sposobem na powizanie midzy sob obiektów w aplikacji, tak e obiekty nie posiadaj informacji o swoich zalenociach i sposobie ich implementacji. Zamiast same uzyskiwa poczenie z obiektami, od których zale, otrzymuj je, bez adnej aktywnoci w nich samych. Poniewa zalene obiekty czsto otrzymuj informacj o obiektach wstrzykiwanych za porednictwem interfejsów, ma miejsce lune wizanie. Poza wstrzykiwaniem zalenoci rzucilimy okiem na obsug AOP w Springu. AOP pozwala logik, która normalnie byaby rozrzucona po caej aplikacji, skupi w jednym miejscu — w aspekcie. Podczas wizania ze sob naszych beanów moe by realizowane wplatanie aspektów w trakcie pracy, skutkujce nadaniem beanom nowej funkcjonalnoci. Wstrzykiwanie zalenoci i AOP s podstaw dziaania Springa. Zatem konieczne jest, by nauczy si uywa tych podstawowych funkcji, by móc korzysta z pozostaej czci moliwoci tego frameworka. Tre tego rozdziau zaledwie musna powierzchni tematu funkcjonalnoci DI oraz AOP w Springu. W nastpnych kilku rozdziaach zagbimy si bardziej w t tematyk. Zatem bez dalszej zwoki przejdmy do rozdziau 2., by nauczy si wizania obiektów midzy sob w Springu za pomoc wstrzykiwania zalenoci.
Tworzymy powizania midzy komponentami
W tym rozdziale omówimy: Q
Deklarowanie komponentów
Q
Wstrzykiwanie przez konstruktory i modyfikatory
Q
Tworzenie powiza midzy komponentami
Q
Sterowanie przebiegiem tworzenia i usuwania komponentów
Czy zdarzyo Ci si, Czytelniku, zosta w kinie po projekcji wystarczajco dugo, by widzie wszystkie napisy na kocu? To niesamowite, jak wiele osób jest zaangaowanych w powstanie przyzwoitego filmu. Poza oczywistymi uczestnikami tego procesu — takimi jak aktorzy, scenarzyci, reyserzy i producenci — pojawiaj si tam te nie a tak oczywici muzycy, ekipa od efektów specjalnych i dyrektorzy artystyczni, e nie wspomn o osobach kluczowych — montaycie dwiku, projektantach kostiumów, makijaystach, koordynatorach kaskaderów, publicystach, pierwszym asystencie kamerzysty, drugim asystencie kamerzysty, projektantach scenografii, kierowniku produkcji i (by moe najwaniejszych) osobach zajmujcych si kateringiem. Teraz wyobra sobie, Czytelniku, jak wygldaby Twój ulubiony film, gdyby adna z wymienionych powyej osób nie odzywaa si do pozostaych. Powiedzmy, e wszyscy dotarli do studio i kady zacz zajmowa si swoimi sprawami bez kogo, kto by wszystko koordynowa. Gdyby reyser zamkn si w sobie i nie powiedzia „krcimy”, wtedy kamerzysta nie zaczby filmowa . To i tak prawdopodobnie nie miaoby znaczenia, poniewa aktorka odtwarzajca gówn rol nadal przebywaaby w swojej garderobie,
50
ROZDZIA 2. Tworzymy powizania midzy komponentami
a owietlenie nie dziaaoby, poniewa nikt nie zatrudni kierownika produkcji. Moe widziae film, który wyglda, jakby wanie tak si stao. Jednak wikszo filmów (a przynajmniej te dobre) to wynik wspólnej pracy tysicy ludzi, dcych do wspólnego celu, którym jest stworzenie kinowego hitu. Pod tym wzgldem wspaniae oprogramowanie niewiele si róni. Kada niebanalna aplikacja jest zbudowana z wielu obiektów, które musz wspópracowa ze sob, by zrealizowa jakie zadanie biznesowe. Obiekty te musz by poinformowane o sobie nawzajem i komunikowa si midzy sob, by zrealizowa postawione przed nimi zadanie. Przykadowo, w aplikacji sklepu internetowego komponent zarzdzajcy zamówieniami moe potrzebowa wspópracy z komponentem zarzdzania produktami i komponentem autoryzacji kart kredytowych. Za one wszystkie prawdopodobnie bd potrzeboway wspópracy z komponentem dostpu do danych, by czyta z bazy danych i zapisywa do niej. Lecz, jak widzielimy w rozdziale 1., tradycyjne podejcie do tworzenia powiza midzy obiektami aplikacji (za pomoc wbudowywania lub odwoa) prowadzi do skomplikowanego kodu, który jest trudny do ponownego uycia, a take do przeprowadzenia testów jednostkowych. W najlepszym razie obiekty te bd wykonyway wicej pracy, ni to potrzebne. W najgorszym ich silne powizanie midzy sob uniemoliwi ich ponowne wykorzystanie lub testowanie. W Springu obiekty nie odpowiadaj za odnajdywanie albo tworzenie innych obiektów, potrzebnych im do dziaania. Zamiast tego referencje do obiektów, z którymi wspópracuj, otrzymuj przez kontener. Na przykad, komponent zarzdzania zamówieniami moe potrzebowa komponentu autoryzacji kart kredytowych — lecz nie musi tworzy komponentu autoryzacji. Musi tylko pokaza , e ma puste rce, a otrzyma modu autoryzacji, z którego bdzie móg korzysta podczas pracy. Czynno tworzenia tych wanie powiza midzy obiektami aplikacji jest istot wstrzykiwania zalenoci (DI) i jest czsto okrelana wizaniem. W tym rozdziale poznamy podstawy wizania beanów za pomoc Springa. Jako e DI jest najbardziej elementarnym dziaaniem Springa, z techniki tej bdziesz korzysta prawie zawsze podczas tworzenia aplikacji na bazie Springa.
2.1.
Deklarujemy komponenty W tym miejscu chciabym Ci powita na pierwszym (i prawdopodobnie ostatnim) corocznym turnieju talentów JavaBean. Zaprosilimy na wystp najbardziej uzdolnione komponenty JavaBean z caego kraju (a waciwie tylko z przestrzeni roboczej naszego rodowiska programistycznego) i w kilku nastpnych rozdziaach urzdzimy rywalizacj, a nasi jurorzy bd przyznawa punkty. Panie i panowie programici Springa, oto Wasz Idol Springa. W naszym turnieju bdziemy potrzebowali pewnej liczby wykonawców, którzy bd zdefiniowani za pomoc interfejsu Performer: package com.springinaction.springidol; public interface Performer { void perform() throws PerformanceException; }
2.1.
Deklarujemy komponenty
51
W turnieju talentów Idol Springa poznamy kilku wspózawodniczcych midzy sob wykonawców, z których kady bdzie implementowa interfejs Performer. Na pocztek przygotujmy scen dla naszego turnieju, przygldajc si podstawom konfiguracji Springa. 2.1.1.
Tworzymy konfiguracj Springa
Jak ju zostao powiedziane, Spring jest frameworkiem opartym na kontenerach. Lecz jeli nie skonfigurujemy Springa, bdziemy mieli pusty kontener, z którego nie bdzie wiele poytku. Musimy skonfigurowa Springa, by poinformowa go, jakie komponenty powinien zawiera i jak je powiza , by mogy wspódziaa midzy sob. Poczwszy od wersji 3.0 Springa, istniej dwa sposoby na konfigurowanie beanów w kontenerze Springa. Tradycyjnie, konfiguracja moe zosta zdefiniowana w jednym lub kilku plikach XML. Lecz od wersji 3.0 mamy take do dyspozycji opcj konfiguracji bazujcej na Javie. Na razie skupimy si na tradycyjnej opcji z plikami XML, lecz konfiguracji Springa bazujcej na Javie przyjrzymy si póniej, w podrozdziale 3.4. Podczas deklarowania beanów w jzyku XML elementem nadrzdnym w pliku konfiguracyjnym Springa jest element ze schematu beanów Springa. Typowy plik XML z konfiguracj moe wyglda nastpujco:
Wewntrz elementu moemy umieci ca nasz konfiguracj Springa, w tym deklaracje elementów . Lecz przestrze nazw beans nie jest jedyn, z jak w Springu bdziemy mie do czynienia. cznie framework Spring posiada dziesi konfiguracyjnych przestrzeni nazw, opisanych w tabeli 2.1. Dodatkowo, poza przestrzeniami nazw nalecymi do rodowiska Spring, wiele projektów bazujcych na Springu, jak na przykad Spring Security, Spring Web Flow czy Spring Dynamic Modules, posiada wasne konfiguracyjne przestrzenie nazw. Bdzie okazja, by w trakcie dalszej lektury przyjrze si przestrzeniom nazw Springa. Lecz na razie zajmijmy si uzupenieniem tego wyranego braku w konfiguracji zapisanej w jzyku XML, dodajc par elementów wewntrz elementu . 2.1.2.
Deklarujemy prosty komponent
W odrónieniu od podobnie nazwanych turniejów talentów, o których moge sysze , Idol Springa nie jest ograniczony wycznie do rywalizacji piosenkarzy. Wielu wystpujcych wykonawców nie potrafi zapiewa czysto nawet jednej nuty. Na przykad jednym z wykonawców jest Juggler (ongler), zdefiniowany na listingu 2.1. Jak widzimy, nasza klasa Juggler robi odrobin wicej, ni tylko implementuje interfejs Performer, potrzebny do zakomunikowania, e ongluje woreczkami z grochem. Domylnie Juggler ongluje trzema woreczkami, lecz przez konstruktor mona mu przekaza inn ich liczb.
52
ROZDZIA 2. Tworzymy powizania midzy komponentami Tabela 2.1. Spring posiada pewn liczb przestrzeni nazw, dziki którym moemy skonfigurowa kontener Springa Przestrze nazw
Zastosowanie
aop
Zawiera elementy pozwalajce na deklarowanie aspektów i na automatyczne tworzenie obiektów poredniczcych dla klas z adnotacj @AspectJ jako aspektów Springa.
beans
Podstawowa pierwotna przestrze nazw Springa, umoliwiajca deklarowanie komponentów i sposobu ich wizania.
context
Zawiera elementy pozwalajce na konfigurowanie kontekstu aplikacji w Springu, w tym moliwo automatycznego wykrywania i automatycznego wizania komponentów, a take wstrzykiwanie obiektów, które nie s bezporednio zarzdzane przez Springa.
jee
Udostpnia elementy integrujce z API Javy EE, takimi jak JNDI oraz EJB.
jms
Dostarcza elementy konfiguracyjne na potrzeby deklarowania POJO sterownych komunikatami.
lang
Umoliwia deklarowanie komponentów, które s implementowane jako skrypty w jzyku Groovy, JRuby lub BeanShell.
mvc
Pozwala na korzystanie w Springu z moliwoci kontrolerów adnotacyjnych, kontrolerów widoków i elementów przechwytujcych.
oxm
Obsuguje konfiguracj mechanizmów odwzorowywania obiektów na pliki XML.
tx
Udostpnia deklaratywn konfiguracj transakcji.
util
Zawiera wybór rónych elementów uytkowych. Daje moliwo deklarowania kolekcji jako komponentów i obsugi elementów zastpczych wasnoci.
Listing 2.1. onglujcy komponent
package com.springinaction.springidol; public class Juggler implements Performer { private int beanBags = 3; public Juggler() { } public Juggler(int beanBags) { this.beanBags = beanBags; } public void perform() throws PerformanceException { System.out.println("ONGLUJ "+beanBags+" WORECZKAMI Z GROCHEM"); } }
Majc zdefiniowan klas Juggler, powitajmy prosz na scenie naszego pierwszego wykonawc, któremu na imi Duke. Duke jest zdefiniowany jako komponent w Springu. Oto sposób, w jaki Duke zosta zdeklarowany w pliku konfiguracyjnym Springa (spring-idol.xml):
2.1.
Deklarujemy komponenty
53
Element jest najbardziej podstawow jednostk konfiguracyjn w Springu. Kae on Springowi utworzy dla nas obiekt. Tu Duke zosta zadeklarowany jako komponent zarzdzany przez Springa, za pomoc niemal najprostszej moliwej deklaracji elementu . Atrybut id nadaje komponentowi nazw, za pomoc której bdziemy si do niego odwoywa wewntrz kontenera Springa. Komponent ten bdzie znany jako duke. A jak wynika z atrybutu class, Duke naley do klasy Juggler. Gdy kontener Springa zaaduje nalece do niego komponenty, utworzy instancj komponentu duke, korzystajc z domylnego konstruktora. W skrócie, duke zostanie utworzony za pomoc nastpujcego kodu Javy:1 new com.springinaction.springidol.Juggler();
Aby Duke móg si zaprezentowa , zaadujemy kontekst aplikacji Springa za pomoc nastpujcego kodu: ApplicationContext ctx = new ClassPathXmlApplicationContext( "com/springinaction/springidol/spring-idol.xml"); Performer performer = (Performer) ctx.getBean("duke"); performer.perform();
Cho nie jest to prawdziwa rywalizacja, Duke moe za pomoc powyszego kodu potrenowa przed wystpem. Uruchomiony, kod ten wywietli nastpujcy napis: ONGLUJ 3 WORECZKAMI Z GROCHEM
Domylnie Duke ongluje jednoczenie tylko trzema woreczkami z grochem. Lecz onglowanie tylko trzema wcale nie jest zbytnio imponujce — tyle potrafi kady. Jeli Duke chciaby mie nadziej na wygranie naszego turnieju talentów, bdzie musia jednoczenie onglowa znacznie wiksz liczb woreczków. Zobaczmy, jak skonfigurowa Duke’a, aby móg zosta mistrzem onglerki. 2.1.3.
Wstrzykujemy przez konstruktory
By zrobi prawdziwe wraenie na jurorach, Duke zdecydowa si poprawi wiatowy rekord, onglujc jednoczenie 15 woreczkami z grochem2. Przypomnijmy sobie, na podstawie listingu 2.1, e klasa Juggler moe zosta utworzona na dwa róne sposoby: Q Q
1 2
Za pomoc domylnego konstruktora. Za pomoc konstruktora przyjmujcego argument typu int, informujcy o liczbie woreczków z grochem, które Juggler bdzie próbowa utrzyma w powietrzu.
Z akcentem na „w skrócie”. Waciwie Spring tworzy komponenty za pomoc odbicia. Ciekawostki o onglowaniu: uznanie za rekordzist w onglowaniu woreczkami z grochem zaley od liczby woreczków i od czasu onglowania. Bruce Sarafian jest posiadaczem kilku rekordów, midzy innymi onglujc 12 woreczkami grochu, zdoa zapa je 12 razy. Innym onglerem rekordzist jest Anthony Gatto, który w roku 2005 onglowa 7 pikami przez 10 minut i 12 sekund. Inny ongler, Peter Bone, twierdzi, e onglowa 13 woreczkami grochu, apic je 13 razy, lecz nie powstao nagranie, które byoby dowodem takiego wyczynu.
54
ROZDZIA 2. Tworzymy powizania midzy komponentami
Cho w punkcie 2.1.2 duke zosta zadeklarowany poprawnie, zosta w tej deklaracji uyty konstruktor domylny klasy Juggler, z powodu czego Duke onglowa jednoczenie tylko trzema woreczkami z grochem. By uczyni z Duke’a wiatowego rekordzist w onglerce, bdziemy musieli uy innego konstruktora. Poniszy kod XML pozwala ponownie zadeklarowa Duke’a, by onglowa 15 woreczkami grochu jednoczenie:
Elementu uywamy, by przekaza Springowi dodatkowe informacje, których uyje podczas tworzenia komponentu. Jeli nie zostanie uyty, jak miao to miejsce w punkcie 2.1.2, wywoany bdzie konstruktor domylny. Lecz tutaj podalimy w elemencie atrybut o wartoci 15, wic wywoany zostanie inny konstruktor klasy Juggler. Teraz podczas wystpu Duke’a zostanie wywietlony nastpujcy napis: ONGLUJ 15 WORECZKAMI Z GROCHEM
onglowanie 15 woreczkami z grochem robi wielkie wraenie. Ale jest jeszcze co, czego o Duke’u nie powiedzielimy. Jest on nie tylko dobrym onglerem, lecz take uzdolnionym recytatorem poezji. onglowanie podczas recytowania poezji wymaga wielkiej dyscypliny umysowej. Jeli Duke poradzi sobie z onglowaniem podczas recytowania sonetu Szekspira, ustawi go to na pozycji pewnego zwycizcy naszej rywalizacji. (Uprzedzaem, e nie bdzie to konkurs talentów podobny do innych!). WSTRZYKUJEMY REFERENCJE DO OBIEKTÓW PRZEZ KONSTRUKTOR
Poniewa Duke jest wicej ni tylko zwykym onglerem — jest onglerem poetyckim — potrzebna nam bdzie dla niego nowa definicja typu onglera, do którego bdzie nalea. Zdefiniowana na listingu 2.2 klasa PoeticJuggler lepiej opisuje uzdolnienia Duke’a. Listing 2.2. Troszk bardziej poetycki ongler
package com.springinaction.springidol; public class PoeticJuggler extends Juggler { private Poem poem; public PoeticJuggler(Poem poem) { super(); this.poem = poem; }
Wstrzykujemy poezj
public PoeticJuggler(int beanBags, Poem poem) { super(beanBags); this.poem = poem; } public void perform() throws PerformanceException { super.perform(); System.out.println(", JEDNOCZENIE RECYTUJC...");
Wstrzykujemy liczb woreczków do onglowania oraz poezj
2.1.
Deklarujemy komponenty
55
poem.recite(); } }
Ten nowy typ onglera ma te same moliwoci co „zwyky” ongler, lecz dodatkowo posiada referencj do poezji, któr ma recytowa . Gdy ju jestemy przy poezji, oto interfejs, który j w ogólny sposób definiuje: package com.springinaction.springidol; public interface Poem { void recite(); }
Jednym z utworów, które Duke najbardziej lubi, jest sonet Szekspira „Gdy los i ludzie czstuj mnie wzgard”3. Klasa Sonnet29 z listingu 2.3 jest implementacj interfejsu Poem, zawierajc definicj tego sonetu. Listing 2.3. Klasa reprezentujca wspaniay utwór angielskiego wieszcza
package com.springinaction.springidol; public class Sonnet29 implements Poem { privatestaticString[] LINES = { "Gdy los i ludzie czstuj mnie wzgard , ", "Chc miosierdzie wzbudzi w guchym niebie; ", "Pacz i al si na dol tward , ", "I kln upadek mój patrz c na siebie. ", "Chc mie bogatsz nadziej przyszoci, ", "Mie rysy innych i przyjació rzesz, ", "Dobra jednego, innego zdolnoci, ", "Gdy tym co moje zgoa si nie ciesz. ", "Lecz gdy od myli tych brzydnie mi ycie, ", "Wraca o tobie myl, a moja dusza ", "Niby skowronek zrywa si o wicie ", "I hymn podnosz c bramy niebios wzrusza; ", "Gdy twej mioci najsodsze wspomnienie ", "Sprawia, e z królem losu nie zamieni." }; public Sonnet29() { } public void recite() { for (inti=0; i < LINES.length; i++) { System.out.println(LINES[i]); } } }
3
Wykorzystano tekst Sonetu 29 w przekadzie Macieja Somczyskiego — przyp. tum.
56
ROZDZIA 2. Tworzymy powizania midzy komponentami
Klasa Sonnet29 moe zosta zadeklarowana jako w Springu za pomoc nastpujcego kodu XML:
Gdy ju wybralimy utwór, musimy tylko poinformowa Duke’a o naszym wyborze. Teraz Duke jest instancj klasy PoeticJuggler, wic bdziemy musieli nieco zmodyfikowa deklaracj opisujcego go elementu :
Jak widzimy na listingu 2.2, nie mamy tutaj domylnego konstruktora. Jedynym sposobem na utworzenie obiektu klasy PoeticJuggler jest uycie konstruktora przyjmujcego argumenty. W tym listingu uylimy konstruktora przyjmujcego dwa argumenty, typu int i typu Poem. Deklarujc beana duke, nadajemy liczbie woreczków z grochem warto 15, zawart w argumencie typu int. Uywamy w tym celu atrybutu value elementu . Nie moemy jednak uy atrybutu value do nadania wartoci drugiemu argumentowi konstruktora, poniewa typ Poem nie jest typem prostym. Zamiast tego uyjemy atrybutu ref, by wskaza , e warto przekazana do konstruktora powinna by referencj do komponentu, nazwanego sonnet29. Cho moliwoci kontenera Springa znacznie przewyszaj proste tworzenie komponentów, moemy sobie wyobrazi , e Spring, napotykajc komponenty sonnet29 i duke, wykona logik odpowiadajc poniszemu kodowi w Javie: Poem sonnet29 = new Sonnet29(); Performer duke=new PoeticJuggler(15, sonnet29);
Teraz Duke podczas wystpu nie tylko ongluje, lecz jednoczenie recytuje Szekspira, w efekcie wypisujc do standardowego strumienia wyjciowego nastpujcy komunikat: ONGLUJ 15 WORECZKAMI Z GROCHEM, JEDNOCZENIE RECYTUJC... Gdy los i ludzie czstuj mnie wzgard , Chc miosierdzie wzbudzi w guchym niebie; Pacz i al si na dol tward , I kln upadek mój patrz c na siebie. Chc mie bogatsz nadziej przyszoci, Mie rysy innych i przyjació rzesz, Dobra jednego, innego zdolnoci, Gdy tym co moje zgoa si nie ciesz. Lecz gdy od myli tych brzydnie mi ycie, Wraca o tobie myl, a moja dusza Niby skowronek zrywa si o wicie I hymn podnosz c bramy niebios wzrusza; Gdy twej mioci najsodsze wspomnienie Sprawia, e z królem losu nie zamieni.
Moliwo tworzenia komponentów za pomoc wstrzykiwania przez konstruktor jest czym wspaniaym. Lecz jak sobie poradzi , gdy bean, który chcemy zadeklarowa , nie posiada publicznego konstruktora? Przyjrzyjmy si sposobom wizania komponentów, które zostaj utworzone za pomoc metod fabryki. TWORZYMY KOMPONENTY ZA POMOC METOD FABRYKI
Czasami jedynym sposobem na utworzenie instancji obiektu jest uycie statycznej metody fabryki. Spring jest przygotowany do wizania komponentów utworzonych przez fabryk, z uyciem atrybutu factory-method w elemencie .
2.1.
57
Deklarujemy komponenty
Aby to lepiej zobrazowa , rozwamy przypadek konfiguracji jako komponentu w Springu klasy singletonowej4. Celem uycia klas singletonowych jest zapewnienie, e zostanie utworzona tylko jedna instancja takiej klasy. Osigamy to przez ograniczenie moliwoci tworzenia instancji klasy jedynie za pomoc statycznej metody fabryki (dlatego klasy singletonowe nazywa si czsto klasami statycznymi). Prostym przykadem klasy statycznej jest klasa Stage (scena), przedstawiona na listingu 2.4. Listing 2.4. Statyczna klasa Stage
package com.springinaction.springidol; public class Stage { private Stage() { } private static class StageSingletonHolder{ static Stage instance=newStage(); }
Leniwie adujemy instancj
public staticStage getInstance(){ return StageSingletonHolder.instance; }
Zwracamy instancj
}
W turnieju talentów Idol Springa chcemy zapewni , e bdzie tylko jedna scena, na której bd si prezentowali zawodnicy. Klasa Stage zostaa zaimplementowana jako singleton, aby zagwarantowa , e nie bdzie moliwoci utworzenia wicej ni jednej instancji tej klasy. Zauwamy jednak, e klasa Stage nie posiada publicznego konstruktora. Zamiast tego statyczna metoda getInstance() po kadym wywoaniu zwraca t sam instancj. (W celu zapewnienia bezpieczestwa pracy wielowtkowej metoda getInstance() korzysta podczas tworzenia instancji singletonowej z techniki leniwej inicjalizacji, zwanej inicjalizacj na danie posiadacza, ang. initialization on demand holder5). W jaki sposób moemy skonfigurowa w Springu klas Stage jako komponent, nie korzystajc z publicznego konstruktora? Na szczcie, element posiada atrybut factory-method, pozwalajcy wskaza metod statyczn, która zostanie wywoana zamiast konstruktora podczas tworzenia instancji klasy. Konfigurujc klas Stage jako komponent w kontekcie Springa, po prostu uyjemy atrybutu factory-method w nastpujcy sposób:
Pokazalimy tu sposób uycia atrybutu factory-method do konfiguracji klasy singletonowej jako komponentu w Springu, lecz doskonale nadaje si on do kadej okolicznoci, gdzie musimy zrealizowa wizanie obiektu utworzonego przez metod statyczn. 4
5
Mówimy tu o wzorcu projektowym Gang Czterech Singletonów, nie za o wprowadzonym przez Springa pojciu definicji komponentu singletonowego. Wicej informacji (po angielsku) o pojciu „initialization on demand holder” pod adresem http://mng.bz/IGYx.
58
ROZDZIA 2. Tworzymy powizania midzy komponentami
Wicej o atrybucie factory-method dowiemy si w rozdziale 4., gdy uyjemy go, by uzyska referencje do aspektów AspectJ, aby móc wstrzykiwa je wraz z zalenociami. 2.1.4.
Ustalamy zakres komponentów
Domylnie wszystkie komponenty Springa s klasami singletonowymi. Gdy kontener udostpnia komponent (czy to za pomoc wizania, czy te jako wynik wywoania nalecej do kontenera metody getBean()), zawsze bdzie to dokadnie ta sama instancja komponentu. Lecz mog si zdarzy sytuacje, gdy bdziemy potrzebowali, by kade kolejne danie udostpnienia komponentu skutkowao utworzeniem jego nowej instancji. W jaki sposób zmieni domylne podejcie Springa, polegajce na tworzeniu klas singletonowych? Gdy deklarujemy w Springu element , mamy moliwo zadeklarowania zakresu tego komponentu. By wymusi tworzenie przez Springa nowej instancji komponentu za kadym razem, powinnimy uy w deklaracji atrybutu scope o wartoci prototype. Dla przykadu przyjmijmy, e bilety na wystpy w naszym turnieju talentów zostan zadeklarowane jako nastpujcy komponent w Springu:
Wane, by kady z widzów przychodzcych na wystpy dosta oddzielny bilet. Gdyby komponent ticket by klas singletonow, wszyscy otrzymaliby dokadnie ten sam bilet. Pierwszemu widzowi by to nie przeszkadzao, lecz wszyscy pozostali zostaliby oskareni o podrabianie biletów! Nadajc atrybutowi scope warto prototype, moemy by pewni, e kady, kto otrzyma dowizanie do komponentu ticket, bdzie dysponowa jego oddzieln instancj. Poza wartoci prototype Spring posiada kilka innych predefiniowanych wartoci atrybutu scope, jak pokazano w tabeli 2.2. Tabela 2.2. Wartoci atrybutu scope w Springu pozwalaj na deklarowanie zasigu definicji komponentu bez potrzeby mozolnego kodowania regu zasigu w samych klasach komponentów Warto atrybutu scope
Efekt
singleton
Ogranicza zasig definicji komponentu do jednej instancji w kontenerze Springa (domylna).
prototype
Pozwala na utworzenie dowolnej liczby instancji komponentu (jednej na uycie).
request
Ogranicza zasig definicji komponentów do dania HTTP. Dopuszczalne stosowanie tylko w jednym z sieciowych kontekstów Springa (takich jak Spring MVC).
session
Ogranicza zasig definicji komponentu do sesji HTTP. Dopuszczalne uycie tylko w jednym z sieciowych kontekstów Springa (takich jak Spring MVC).
global-session
Ogranicza zasig definicji komponentu do globalnej sesji HTTP. Dopuszczalne uycie tylko w kontekcie portletów.
W wikszoci kodu, jaki bdziemy kiedykolwiek pisa , prawdopodobnie bdziemy chcieli pozosta przy domylnym zasigu singleton, lecz zasig prototype moe by przydatny w zastosowaniach, gdzie bdziemy chcieli uy Springa jako fabryki nowych instancji
2.1.
Deklarujemy komponenty
59
obiektów domenowych. Jeli obiekty domenowe zostan zadeklarowane jako komponenty o zasigu prototype, konfigurowanie ich w Springu okazuje si równie atwe, jak kadego innego komponentu. Jednak Spring gwarantuje utworzenie unikalnej instancji za kadym daniem komponentu o zasigu prototype. Uwany czytelnik zorientuje si, e pojcie klasy singletonowej w Springu jest ograniczone do zasigu kontekstu Springa. W odrónieniu od prawdziwych klas singletonowych, które gwarantuj powstanie tylko jednej instancji klasy w danym mechanizmie adowania klas, bean o zasigu singleton w Springu gwarantuje wycznie powstanie jednej instancji okrelonej definicji komponentu w danym kontekcie aplikacji. Nic nas nie powstrzyma przed utworzeniem kolejnych instancji tej samej klasy w tradycyjny sposób, a nawet zdefiniowaniem wikszej liczby elementów , które tworzyyby instancje tej samej klasy. 2.1.5.
Inicjalizujemy i likwidujemy komponenty
Gdy tworzona jest instancja beana, moe by konieczne wykonanie pewnych czynnoci inicjalizujcych, aby doprowadzi go do stanu uywalnoci. Podobnie, gdy bean ju nie jest wicej potrzebny i zostaje usunity z kontenera, moe by potrzebne posprztanie po nim. Aby umoliwi przejcie kontroli nad tworzeniem i niszczeniem beanów, Spring pozwala nam wpywa na cykl ycia komponentu. Chcc zdefiniowa sposób tworzenia i niszczenia komponentu, uywamy po prostu w deklaracji elementu parametru init-method, destroy-method lub obydwóch. Atrybut init-method wskazuje metod, która zostanie wywoana dla komponentu natychmiast po utworzeniu jego instancji. Podobnie, metoda wskazywana przez atrybut destroy-method zostanie wywoana bezporednio przed usuniciem komponentu z kontenera. By to zobrazowa , wyobramy sobie, e mamy klas Javy, nazwan Auditorium, reprezentujc hal widowiskow, w której bdzie si odbywa nasz turniej talentów. Prawdopodobnie klasa Auditorium bdzie wykonywaa wiele czynnoci, lecz na razie skupmy si na dwóch sprawach istotnych podczas rozpoczynania i koczenia przedstawienia: wczaniu i wyczaniu owietlenia. By obsuy te dwie podstawowe czynnoci, klasa Auditorium mogaby posiada metody turnOnLights() i turnOffLights(): public class Auditorium { public void turnOnLights() { ... } public void turnOffLights() { ... } }
Szczegóy tego, co si dzieje wewntrz metod turnOnLights() i turnOffLights(), nie s strasznie istotne. Wane, by metoda turnOnLights() bya wywoana na pocztku, a metoda turnOffLights() na kocu. W tym celu uyjemy atrybutów init-method i destroy-method podczas deklarowania komponentu auditorium:
60
ROZDZIA 2. Tworzymy powizania midzy komponentami
Zastosowanie takiej deklaracji powoduje wywoanie metody turnOnLights() zaraz po utworzeniu instancji komponentu auditorium, pozwalajc na wykonanie zadania owietlenia miejsca wystpów. A tu przed usuniciem komponentu z kontenera i porzuceniem go w celu wyczenia wiate zostanie wywoana metoda turnOffLights(). Interfejsy InitializingBean i DisposableBean Alternatywnym sposobem na zdefiniowanie metod inicjujcych i likwidujcych dla komponentu jest dopisanie do klasy komponentu implementacji zdefiniowanych w Springu interfejsów InitializingBean i DisposableBean. Kontener Springa traktuje w szczególny sposób komponenty, które implementuj te interfejsy, pozwalajc wpywa na ich cykl ycia. Interfejs InitializingBean zawiera deklaracj metody afterPropertiesSet(), która suy jako metoda inicjalizujca. Z kolei w interfejsie DisposableBean zadeklarowano metod destroy(), która zostaje wywoana, gdy komponent jest usuwany z kontekstu aplikacji. Gówn korzyci z uycia tych interfejsów cyklu yciowego jest moliwo automatycznego wykrywania przez kontener Springa komponentów, które implementuj te interfejsy, bez koniecznoci uycia jakiejkolwiek zewntrznej konfiguracji. Wad implementowania tych interfejsów jest silne zwizanie komponentów naszej aplikacji z API Springa. Z tego jednego powodu zalecam poleganie bardziej na atrybutach init-method i destroy-method podczas inicjowania i likwidowania komponentów. Jedyn sytuacj, w której moglibymy preferowa udostpniane przez Springa interfejsy cyklu ycia, byoby pisanie komponentów tworzcych rodowisko, które bd wykorzystywane wycznie wewntrz kontenera Springa.
DOMY LNE ATRYBUTY INIT-METHOD I DESTROY
Jeli wiele sporód komponentów w pliku definicji kontekstu bdzie miao metody inicjujce lub likwidujce o tej samej nazwie, nie musimy deklarowa atrybutów init-method czy te destroy-method dla kadego z osobna. Moemy zamiast tego skorzysta z atrybutów default-init-method i default-destroy-method w elemencie : ...
Atrybut default-init-method definiuje metod inicjalizacji dla wszystkich komponentów w danej definicji kontekstu. Podobnie atrybut default-destroy-method definiuje wspóln dla wszystkich komponentów w danej definicji kontekstu metod likwidujc. W tym wypadku damy, by Spring inicjowa wszystkie komponenty w pliku definicji kontekstu, wywoujc metod turnOnLights(), i by likwidowa je za pomoc metody turnOffLights() (jeli takie metody istniej — w przeciwnym razie nic si nie stanie).
2.2.
2.2.
Wstrzykujemy wartoci do waciwoci komponentu
61
Wstrzykujemy wartoci do waciwoci komponentu W typowych zastosowaniach waciwoci komponentu JavaBean s polami prywatnymi, wyposaonymi w pary metod dostpowych w formie setXXX() i getXXX(). Podczas konfigurowania waciwoci Spring korzysta ze wstrzykiwania ich wartoci przez metody dostpowe. By zademonstrowa inny rodzaj techniki DI w Springu, powitajmy na scenie kolejnego wykonawc. Kenny jest uzdolnionym instrumentalist, zdefiniowanym przez klas Instrumentalist, jak na listingu 2.5. Listing 2.5. Definicja wykonawcy, którego talent dotyczy instrumentów muzycznych
package com.springinaction.springidol; public class Instrumentalist implements Performer { public Instrumentalist() { } public void perform() throws PerformanceException { System.out.print("Gram " + song + " : "); instrument.play(); } private String song; public void setSong(String song) { this.song = song; }
Wstrzykujemy utwór
public String getSong() { return song; } public String screamSong() { return song; } private Instrument instrument; public void setInstrument(Instrument instrument) { this.instrument = instrument; }
Wstrzykujemy instrument
}
Na listingu 2.5 widzimy, e klasa Instrumentalist posiada dwie waciwoci: song i instrument. Waciwo song zawiera tytu utworu, który bdzie gra nasz instrumentalista, i tytu ten zostanie uyty w metodzie perform(). Waciwo instrument zawiera referencj do instrumentu, na którym instrumentalista bdzie gra. Poniej pokazano definicj interfejsu Instrument: package com.springinaction.springidol; public interface Instrument { public void play(); }
62
ROZDZIA 2. Tworzymy powizania midzy komponentami
Poniewa klasa Instrumentalist posiada domylny konstruktor, Kenny moe zosta zadeklarowany jako w Springu za pomoc poniszego kodu XML:
Cho Spring nie bdzie mia problemu, by utworzy komponent kenny jako instancj klasy Instrumentalist, Kenny bdzie mia spore trudnoci, wystpujc bez utworu i instrumentu. Zobaczmy, jak przekaza Kenny’emu wartoci pól song i instrument za pomoc wstrzykiwania przez metody ustawiajce. 2.2.1.
Wstrzykujemy proste wartoci
Waciwoci komponentów moemy konfigurowa w Springu, posugujc si elementem . Pod wieloma wzgldami element jest podobny do , z tym e zamiast wstrzykiwa wartoci przez argumenty konstruktora, element pozwala na wstrzykiwanie przez wywoanie metod ustawiajcych waciwoci. By to zobrazowa , przekamy Kenny’emu utwór do wykonania, korzystajc ze wstrzykiwania przez metody ustawiajce. Poniszy kod XML zawiera poprawion deklaracj komponentu kenny.
Gdy zostanie utworzona instancja klasy Instrumentalist, Spring uyje metod ustawiajcych do wstrzykiwania wartoci do waciwoci wskazanych elementami . Element w tym kodzie XML nakazuje Springowi wywoanie metody set ´Song(), która nada waciwoci song warto "Jingle Bells". W tym wypadku uywamy atrybutu value elementu , by wstrzykn do waciwoci warto typu String. Lecz element nie jest ograniczony do wstrzykiwania wartoci typu String. Atrybut value moe take przekazywa wartoci numeryczne (typu int, float, java.lang.Double i tak dalej), a take wartoci typu boolean. Dla przykadu zaómy, e klasa Instrumentalist posiada waciwo age, typu int, wskazujc wiek naszego instrumentalisty. Moglibymy wiek Kenny’ego poda za pomoc poniszego kodu XML:
Zauwamy, e atrybut value zosta uyty w dokadnie ten sam sposób podczas przekazywania wartoci numerycznych i wartoci typu String. Spring ustali waciwy typ dla wartoci na podstawie typu waciwoci. Poniewa waciwo age reprezentuje warto typu int, Spring wie, e naley dokona konwersji wartoci 37 na typ int przed wywoaniem metody setAge(). Moliwo uycia elementu do konfigurowania prostych waciwoci beana jest wspaniaa, lecz DI pozwala na znacznie wicej ni wizanie zakodowanych na sztywno
2.2.
Wstrzykujemy wartoci do waciwoci komponentu
63
wartoci. Prawdziw warto DI stanowi moliwo wizania obiektów wspópracujcych w ramach aplikacji, tak e nie musz same ustanawia powiza midzy sob. By si o tym przekona , zobaczmy, w jaki sposób mona przekaza Kenny’emu instrument, na którym bdzie móg zagra . 2.2.2.
Wstrzykujemy referencje do innych beanów
Kenny jest uzdolnionym instrumentalist i potrafi zagra na prawie kadym instrumencie, jaki otrzyma. Dopóki taki instrument bdzie implementowa interfejs Instrument, Kenny poradzi sobie z wydobyciem z niego dwiku. Oczywicie, ma on swój ulubiony instrument. Jego wybranym instrumentem jest saksofon, zdefiniowany na listingu 2.6 za pomoc klasy Saxophone. Listing 2.6. Saksofon jest implementacj interfejsu Instrument
package com.springinaction.springidol; public class Saxophone implements Instrument { public Saxophone() { } public voidplay() { System.out.println("TRUTU TUTU TU"); } }
Zanim bdziemy mogli Kenny’emu wrczy saksofon, by na nim zagra, powinnimy zadeklarowa go jako komponent w kontenerze Springa. Mona to zrobi za pomoc poniszego kodu XML:
Zauwamy, e klasa Saxophone nie ma adnych waciwoci, którym trzeba by byo nada warto . W konsekwencji nie ma potrzeby deklarowania elementów dla komponentu saxophone. Po zadeklarowaniu komponentu saxophone jestemy gotowi, by przekaza go Kenny’emu, by móg na nim zagra . Poniej przedstawiono modyfikacj komponentu kenny, która korzysta ze wstrzykiwania przez metod ustawiajc podczas nadawania wartoci waciwoci instrument:
Teraz do komponentu kenny zostay wstrzyknite wartoci wszystkich jego waciwoci i Kenny jest gotów do wystpu. Podobnie jak w przypadku Duke’a, moemy zaprosi Kenny’ego do rozpoczcia wystpu, wykonujc poniszy kod Javy (by moe w metodzie main()):
64
ROZDZIA 2. Tworzymy powizania midzy komponentami ApplicationContext ctx = new ClassPathXmlApplicationContext( "com/springinaction/springidol/spring-idol.xml"); Performer performer = (Performer) ctx.getBean("kenny"); performer.perform();
To nie jest dokadnie ten kod, który zostanie uruchomiony podczas turnieju Idol Springa, lecz daje on Kenny’emu moliwo , by troch po wiczy . Po uruchomieniu tego kodu wywietlony zostanie poniszy napis: Gram Jingle Bells : TRUTU TUTU TU
Jednoczenie mamy tu zobrazowan wan koncepcj. Porównujc ten kod z kodem rozpoczynajcym wystp Duke’a, zauwaymy, e nie róni si zbyt mocno. Waciwie jedyn rónic jest nazwa komponentu pobranego ze Springa. Kod jest identyczny, nawet mimo tego, e za pierwszym razem rozpoczyna wystp onglera, za za drugim instrumentalisty. To jest nie tyle waciwo Springa, co korzy z programowania z uyciem interfejsów. Odwoujc si do wykonawcy przez interfejs Performer, moemy na lepo wywoywa wystp wykonawcy, niezalenie, czy bdzie to poetycki ongler, czy saksofonista. Z tego powodu Spring zachca do korzystania z interfejsów. A jak si przekonamy, interfejsy wspópracuj rami w rami z technik DI, zapewniajc lune wizanie. Jak wspomnielimy, Kenny potrafi gra na prawie kadym instrumencie, który otrzyma, dopóki implementuje on interfejs Instrument. Cho jego ulubionym instrumentem jest saksofon, moemy poprosi Kenny’ego, by zagra na fortepianie. Na przykad zaómy, e mamy nastpujc klas Piano, zdefiniowan na listingu 2.7. Listing 2.7. Fortepian jest implementacj interfejsu Instrument
package com.springinaction.springidol; public class Piano implements Instrument { public Piano() { } public void play() { System.out.println("PLIM PLIM PLIM "); } }
Klas Piano moemy zadeklarowa jako w Springu za pomoc poniszego kodu XML:
Gdy ju dostpny jest fortepian, zmiana instrumentu, na jakim gra Kenny, jest tak prosta, jak zmiana deklaracji komponentu kenny w nastpujcy sposób:
2.2.
Wstrzykujemy wartoci do waciwoci komponentu
65
Po tej zmianie Kenny bdzie gra na fortepianie zamiast saksofonu. Jednak poniewa klasa Instrumentalist otrzymuje informacje na temat swojej waciwoci instrument tylko przez interfejs Instrument, nie trzeba niczego zmienia w klasie Instrumentalist, by obsuy now implementacj interfejsu Instrument. Cho instrumentalista zdefiniowany klas Instrumentalist moe gra na instrumentach zdefiniowanych w klasach Saxophone czy Piano, nie jest silnie zwizany z adn z nich. Jeli Kenny zdecyduje si zagra na cymbaach, jedyn potrzebn zmian bdzie utworzenie klasy HammeredDulci ´mer i zmiana waciwoci instrument w deklaracji komponentu kenny. WSTRZYKUJEMY ZAGNIE D ONE KOMPONENTY
Widzielimy, e Kenny potrafi gra na saksofonie, fortepianie lub dowolnym instrumencie, który implementuje interfejs Instrument. Lecz prawd jest take, e komponenty saxophone i piano mog by wspóuytkowane przez dowolne inne komponenty dziki wstrzykiwaniu do ich waciwoci instrument. Zatem nie tylko Kenny moe zagra na dowolnym instrumencie implementujcym interfejs Instrument, lecz take dowolny komponent klasy Instrumentalist moe gra na beanie saxophone. Waciwie komponenty czsto wspóuytkuj inne komponenty w ramach tej samej aplikacji. Problem ley w tym, e Kenny jest bardzo wyczulony na punkcie skutków dla higieny w zwizku z udostpnianiem innym do uycia jego saksofonu. Wolaby zatrzyma swój saksofon dla siebie. By pomóc Kenny’emu unikn zarazków, posuymy si wygodn technik Springa, znan jako zagnie d one komponenty. Jako programista Javy prawdopodobnie jeste, Czytelniku, oswojony z koncepcj zagniedonych klas — klas zdefiniowanych wewntrz innej klasy. Podobnie zagniedone komponenty s komponentami zdefiniowanymi wewntrz innego komponentu. W celu zobrazowania tego przyjmijmy tak oto now konfiguracj komponentu kenny, w której saksofon jest zadeklarowany jako komponent zagniedony:
Jak widzimy, zagniedony komponent jest zdefiniowany przez zadeklarowanie elementu bezporednio jako potomnego wzgldem elementu , do którego bdzie wstrzyknity. W tym wypadku komponent Saxophone zostanie utworzony i powizany od wewntrz z waciwoci instrument Kenny’ego. Zagniedone komponenty nie s ograniczone do wstrzykiwania przez metody ustawiajce. Moemy take wiza zagniedone komponenty za porednictwem argumentów konstruktora, jak pokazano w poniszej nowej wersji deklaracji beana duke:
66
ROZDZIA 2. Tworzymy powizania midzy komponentami
Widzimy tu, e instancja klasy Sonnet29 zostanie utworzona jako zagniedony komponent, nastpnie wysany jako argument do konstruktora klasy PoeticJuggler. Zauwamy, e zagniedone komponenty nie maj atrybutu id. Cho deklaracja zagniedonego komponentu z atrybutem id jest zupenie prawidowa, nie jest to konieczne, poniewa nigdy nie odwoujemy si do zagniedonego komponentu za pomoc nazwy. To akcentuje gówn wad uywania zagniedonych komponentów: nie mona uy ich ponownie. Zagniedone komponenty s uyteczne do jednorazowego wstrzykiwania i nie mog si do nich odwoywa inne komponenty. Mona take zauway , e uycie zagniedonych definicji komponentów ma negatywny wpyw na czytelno kodu XML w plikach kontekstu Springa. 2.2.3.
Wiemy waciwoci w przestrzeni nazw p Springa
Wizanie wartoci i referencji z waciwociami komponentów za pomoc elementu nie jest zbyt trudne. Mimo to przestrze nazw p Springa daje moliwo wizania waciwoci komponentów w sposób niewymagajcy uycia tak wielu trójktnych nawiasów. Przestrze nazw p posiada schemat pod adresem URI http://www.springframework. org/schema/p. Aby z niej korzysta , wystarczy doda jej deklaracj do pliku konfiguracyjnego XML Springa:
Z tak deklaracj moemy w elemencie uywa atrybutów z przedrostkiem p: podczas wizania waciwoci. Dla przykadu spójrzmy na ponisz deklaracj komponentu kenny:
Atrybut p:song posiada warto "Jingle Bells", dziki czemu uzyskujemy powizanie waciwoci song z t wartoci. Jednoczenie atrybut p:instrument-ref ma warto "saxophone", w efekcie wic waciwo instrument z referencj do komponentu o identyfikatorze saxophone. Przyrostek -ref suy jako podpowied dla Springa, by uy do wizania referencji zamiast samej wartoci. Wybór midzy elementem i przestrzeni nazw p naley do Ciebie. Oba te sposoby dziaaj jednakowo dobrze. Gówn korzyci z uycia przestrzeni nazw p jest wiksza zwizo zapisu. Dobrze si to sprawdza podczas pisania przykadów do ksiki, która ma ustalone na sztywno pooenie marginesów. Z tego powodu podczas lektury tej ksiki od czasu do czasu napotkasz na przykady z uyciem przestrzeni nazw p — zwaszcza tam, gdzie moe brakowa przestrzeni w poziomie. W tym miejscu wiemy, e talent Kenny’ego pozwala mu gra na prawie kadym instrumencie. Niemniej jednak podlega on jednemu ograniczeniu: potrafi gra w danym
2.2.
Wstrzykujemy wartoci do waciwoci komponentu
67
momencie tylko na jednym instrumencie. Jako nastpny na scenie turnieju talentów Idol Springa pojawi si Hank, wykonawca, który potrafi gra na wielu instrumentach jednoczenie. 2.2.4.
Wiemy kolekcje
Do tej chwili dowiedzielimy si, jak za pomoc konfiguracji Springa zarówno nadawa waciwociom proste wartoci (za pomoc atrybutu value), jak i tworzy waciwoci zawierajce referencje do innych komponentów (z uyciem atrybutu ref). Lecz atrybuty value i ref s uyteczne tylko w przypadku pojedynczych waciwoci. W jaki sposób Spring pozwoli nam uy wielu wartoci waciwoci — co z sytuacj, gdy waciwo jest kolekcj wartoci? Spring posiada cztery rodzaje elementów konfiguracyjnych kolekcji, które przydadz si podczas konfigurowania kolekcji wartoci. W tabeli 2.3 przedstawiono te elementy i obszar przydatnoci kadego z nich. Tabela 2.3. Podobnie jak Java posiada kilka rodzajów kolekcji, Spring pozwala na wstrzykiwanie kilku ich rodzajów Element reprezentujcy kolekcj
Uyteczny do...
Wizania z list wartoci, pozwalajc na wystpowanie powtórze.
Wizania ze zbiorem wartoci, zapewniajcym brak powtórze.