Spring Framework – představení J2EE lightweight kontejneru
Kdybychom žili v ideálním programátorském světě, nebylo by nástrojů, jako je Spring Framework, zapotřebí. Protože v takovém světě nežijeme a jsme tedy postaveni před reálné problémy, můžeme s povděkem kvitovat služby, které nám framework Spring poskytuje. Spring je spojen s přívlastkem J2EE lightweight kontejner. Ona dvě magická E možná vyvolají u leckterých vývojářů lehké pochyby o jeho využití, ale opak je pravdou. Spring nabízí celou škálu služeb a rozhodně platí, že J2EE != EJB.
Motivace
Základní motivací pro vývoj systému Spring Framework bylo a je usnadnění vývoje v oblasti enterprise aplikací. Pokud vás fráze „enterprise aplikace“ leká stejně jako ortodoxního muslima pravá jihočeská zabijačka, mohu vás uklidnit. Enterprise aplikace je jedním z nejfrekventovanějších buzz-words, na které můžete v současnosti narazit. Pojďme si nastínit, co znamená ono usnadnění vývoje.
- Pomoc při odstranění těsných programových vazeb jednotlivých POJO objektů a vrstev za pomoci návrhového vzoru Inversion of Kontrol.
- Možnost volby implementace (EJB, POJO) business vrstvy pro aplikační architekturu a ne naopak (tedy aby architektura předepisovala implementaci).
- Řešení různých aplikačních domén bez nutnosti použití EJB, například transakční zpracování, podpora pro remoting business vrstvy formou webových služeb či RMI.
- Podpora implementace komponent pro přístup k datům, ať již formou přímého JDBC či ORM (object-relation mapping) technologií a nástrojů jako Hibernate, TopLink, iBatis nebo JDO.
- Odstranění závislosti na roztroušených konfiguracích a pracného dohledávání jejich významu.
- Abstrakce vedoucí ke zjednodušenému používání dalších části J2EE, jako například JMS, JMX, JavaMail, JDBC, JCA nebo JNDI.
- Usnadnění používání a psaní unit testů.
- Správa a konfigurační management business komponent.
Pokud se bavíme o usnadnění vývoje enterprise aplikací, dříve nebo později narazíme na magické zaklínadlo v podobě technologie EJB (Enterprise Java Beans). Můžeme si to říci celkem bez okolků, Spring je tu také jako alternativu k EJB. A proč vlastně hledat alternativu k EJB?
- I přes četné změny EJB specifikace navazuje na verzi 1.0 z roku 1998, která odrážela tehdejší stav včetně EJB modelu.
- Přílišná komplexnost EJB, pro jednu komponentu potřebujeme čtyři soubory – component interface (Home nebo Remote), business interface, vlastní implementaci a deployment descriptor. Home a remote rozhraní přitom nemají žádnou souvislost s business funkcí dané komponenty.
- Invazivnost EJB, business logika běží pouze uvnitř EJB kontejneru.
- Problém s unit testy, viz invazivnost.
- Špatná přenositelnost komponent díky proprietárním deployment descriptorům v rámci jednotlivých kontejnerů.
Samozřejmě EJB má své místo na slunci, například tam, kde potřebujeme distribuované transakce. Na druhou stranu, i vývojáři používající EJB kopírují pravidlo 80 ku 20. Tedy – 80 % vývojářů bohatě vystačí s dvaceti procenty toho, co nabízí EJB.
Spring versus EJB
Pomalu nám ve vzduchu visí otázka porovnání Springu a EJB. Toto porovnání je ovšem trochu přitažené za vlasy, neboť se míchají jablka a hrušky. Především si musíme uvědomit, že EJB je specifikace spadající do větší množiny nazvané J2EE. Na druhou stranu můžeme porovnat možnosti v rámci jednotlivých aplikačních domén (transakce, bezpečnost, remoting, persistence mechanismus a podobně), před které jsme postaveni při použití EJB či Springu. Nadto je třeba poznamenat, že i v případě použití EJB není Spring nijak diskvalifikován. Spring se může velice dobře využít i pro zjednodušení práce s EJB.
Doména | EJB | Spring |
---|---|---|
Transakční zpracování |
|
|
Persistence mechanismus |
|
|
Bezpečnost |
|
|
Remoting |
|
|
Spring samozřejmě nabízí služby a podporu nad rámec EJB, jenom výčtem – vlastní MVC (Model View Controller) s podporou integrace různorodých technologií (JSP+JSTL+Tiles, Velocity, FreeMarker, XSLT, JasperReports), podporu integrace s MVC a web frameworky (Struts, Tapestry, JSF a WebWork), podporu AOP (Aspect Oriented Programming), podporu unit testingu, plánovaného zpracování (job scheduling) a další. Je důležité poznamenat, že pro využití Springu nepotřebujete vůbec žádný server jako v případě EJB (samozřejmě pokud nepoužijete Spring pro EJB).
EJB 3.0
Povídání kolem Springu a EJB nemůžeme zakončit beze zmínky o připravovaném EJB 3.0. Hlavním hnacím motorem pro EJB 3.0 bylo zjednodušení vývoje. S nadsázkou můžeme říct, že úspěch Springu a myšlenek, které rozvinul – Inversion of Control, POJO model s objektovou orientací bez nutnosti implementace zbytečných rozhraní nesouvisejících s business funkcí daného objektu nebo integrace s persistence frameworky (Hibernate, TopLink) – se staly předlohou pro EJB 3.0. Specifikace EJB 3.0 pomalu spěje k finální podobě a již nyní je možno otestovat preview EJB 3.0, které poskytují někteří dodavatelé aplikačních serverů, například JBoss či Oracle Application Server.
Koncept
Všechny vlastnosti a funkce Springu, o kterých jsme se zatím zmínili, lze schématicky začlenit do sedmi modulů, které jsou zobrazeny na následujícím obrázku.
Základní moduly frameworku Spring (plná velikost, cca 13 kB)
Jednotlivé moduly lze využívat v rámci kontejneru (nemá nic společného s EJB kontejnerem) a jeho inicializace je otázkou jedné řádky kódu. Kontejner je prostředí, ve kterém se odehrává život všech objektů, které pomocí Springu spravujeme.
Core modul
Core modul tvoří základ celého frameworku a poskytuje funkčnost (Dependency Injection) pro řízení práce celého kontejneru. Základ tohoto modulu tvoří implementace BeanFactory, která se stará o životní cyklus jednotlivých POJO objektů – vytvoření, nastavení vazeb mezi jednotlivými objekty, inicializace, poskytování objektů k použití a ukončení při zastavení kontejneru.
Context modul
Context modul zobecňuje práci s BeanFactory na úroveň registru (obdoba JNDI) a přidává funkční nadstavbu, například v podobě podpory resources bundles, JNDI a podobně. Tím nejzajímavějším je ovšem odstínění od BeanFactory. Context modul hraje roli prostředníka mezi klientským kódem a BeanFactory. Inicializace je možná mnohem transparentnějším způsobem, například servlet kontainerem či JUnit testem.
DAO modul
Zkratka DAO znamená Data Access Object a tento modul poskytuje abstraktní vrstvu pro práci s JDBC API. Umožňuje odstranění opakujícího se kódu (získání connection, vytváření statementu, iterování přes result set), kterým trpí většina aplikací pracujících s JDBC API. Samozřejmostí je podpora deklarativní definice transakcí a především exception handling převádějící java.sql.SQLException
na inteligentní hierarchii běhových alias runtime výjimek.
AOP
AOP je modul implementující podporu pro aspektově orientované programování. Umožňuje separovat části kódu prolínající se celou aplikací (autorizace, logování, transakce) do takzvaných aspektů a jejich následnou aplikaci na jakýkoli POJO objekt. Využití AOP modulu se prolíná celým frameworkem a jedná se o jednu z nejsilnějších vlastností Springu.
ORM
Modul určený k podpoře integrace OR frameworků jako Hibernate nebo iBatis. Při použití tohoto modulu je samozřejmě možné využít všech dalších funkčností Springu, jako je například podpora transakcí a AOP.
Web
Modul určený k podpoře integrace s web frameworky jako Struts, WebWork a JSF implementacemi. Dále poskytuje podpůrné třídy, například pro zpracování uploadu souborů, i18n či práci s cookies.
Web MVC
Implementace MVC určená pro webové aplikace, opět je možno využít všech dalších funkčností Springu.
Použití modulů
Kdybychom chtěli postavit za pomoci Springu kompletně celou střední vrstvu J2EE aplikace, mohlo by využití jednotlivých modulů a jejich funkčnosti vypadat následovně.
Schéma J2EE aplikace plně postavené na možnostech Springu (plná velikost, cca 13 kB)
Na vrcholu sedí MVC modul využívající služeb Web modulu, jako validace vstupních dat, podpora pro zpracování multipart obsahu, napojení vstupních dat na Domain model aplikace nebo integrace s vhodnou view technologii pro prezentaci dat. Uprostřed leží business vrstva s definicí business logiky v POJO objektech, na této vrstvě jsou realizovány transkace pomocí AOP modulu. Business vrstva je vystavena díky podpoře remotingu jako webová služba. Data pro business logiku poskytuje Data Access vrstva řešená za pomoci ORM a DAO modulu. Celá aplikace pak může běžet jak v servletovém kontejneru typu Tomcat/Jetty, tak v plnohodnotném J2EE serveru.
Spring nemusí nutně pokrývat celou aplikaci, ale můžeme jej využít takřka v jakémkoli scénáři, například v součinnosti se Struts, EJB nebo pro tvorbu aplikace využívající JDBC. Stejně tak není zapotřebí k využití Springu používat Tomcat. Spring, respektive BeanFactory lze nastartovat stejně dobře programově a pohodlnou cestou. Nevěříte? Tak se podívejte na třídu, kterou používám pro integrační testy a která se postará o inicializaci kontextu (jednotlivé testy si pak berou z contextu patřičné objekty k otestování).
(Pozn. aut.: Spring v současné verzi poskytuje abstraktní třídu pro JUnit testy, která odesílá zde uvedený helper do propadliště dějin. Tedy alespoň z pohledu JUnit testů, jinak je samozřejmě použitelný.)
/**
* Pomocná třída pro testovací objekty. Loaduje testovací aplikační
* kontext Springu a ten poskytuje pro využítí v unit testech.
*
*/
public class SpringHelper {
private static ApplicationContext ac =
new FileSystemXmlApplicationContext(„config/spring/spring-testcontext.xml“);
public static ApplicationContext getAppContext(){
return ac;
}
}
Spring v akci
Nemělo by význam v tomto seznámení zabíhat do jednotlivých ukázek bez smysluplného cíle a přitom se snažit o demonstraci síly Springu. Mnohem zajímavější bude ukázat tvorbu konkrétní webové aplikace pomocí Springu, a to s různými variacemi na úrovni jednotlivých vrstev (nahrazení Spring MVC za Struts , změna implementace datové vrstvy z JDBC na Hibernate). Rád bych, abychom nezůstávali pouze u Springu, takže pokud budeme probírat datovou vrstvu, určitě si vysvětlíme i návrhový vzor Data Access Object. Pokud se budeme bavit o Hibernate, určitě si probereme ORM přístup, stejně tak si osvětlíme základy aspektově orientovaného programování.
Definice termínů
POJO
Termín POJO je zkratkou Plain Old Java Objects – volně přeloženo jako „staré dobré Java objekty“. Termín POJO formulovali Martin Fowler, Rebbecca Parsons a >Josh MacKenzie. Označuje objekty, které nejsou svázané technologicky specifickým rozhraním. Jediné rozhraní těchto objektů je definováno business službami, které poskytují.
public inteface VypujceneKnihy {
public List getSeznamVypujcenychKnih(Date obdobi);
public List getSeznamVypujcenychKnih(String userId);
}
public class Knihovna implements VypujceneKnihy {
public List getSeznamVypujcenychKnih(Date obdobi){
…
}
public List getSeznamVypujcenychKnih(String userId){
…
}
}
Inversion of Control
Vzor Inversion of Control (IoC) řeší těsné vazby mezi aplikačními objekty, které jsou těsně svázány ve zdrojovém kódu. Řekněme, že máme objekt „Knihovna“, který využívá služeb objektů „Vypujcky“ a „Registr knih“. Instanciování a inicializace objektů „Vypujcky“ a „Registr knih“ je řešena přímo v objektu „Knihovna“.
public class Knihovna implements VypujceneKnihy{
private Vypujcky vypujcky;
private Registr registr;
public Knihovna(){
vypujcky = new Vypujcky();
registr = new LokalniRegistrKnih();
registr.setDataSource(„foo.xml“);
registr.initialize();
}
public List getSeznamVypujcenychKnih(Date obdobi){
//prace s objketem vypujcky a registr
}
}
Těsná vazba objektu „Knihovna“ na objekty „Vypujcky“ a „LokalniRegistrKnih“ má za následek, že „Knihovna“ musí instancovat konkrétní třídy a navíc je posléze zinicializovat (pokud je to potřeba). První problém nastává při inicializaci, neboť objekt „Knihovna“ musí správně zinicializovat objekt „LokalniRegistrKnih“, tedy nastavit zdroj dat, a poté zavolat inicializační metodu. Další problém je ve výběru konkrétních instancí, viz „LokalniRegistrKnih“. V případě, že bychom chtěli zaměnit „LokalniRegistrKnih“ například za „RozsirenyRegistrKnih“, museli bychom kód změnit a znovu zkompilovat.
Vzor Inversion of Control přenáší odpovědnost za vytváření, inicializaci a provázání objektů ven z aplikačního kódu, na takzvaný IoC kontejner. Objekty mají pouze povinnost poskytnout rozhraní pro vložení potřebných objektů z vnějšku.
public class Knihovna implements VypujceneKnihy{
private Vypujcky vypujcky;
private Registr registr;
public Knihovna(){
}
public List getSeznamVypujcenychKnih(Date obdobi){
//prace s objketem vypujcky a registr
}
public void setVypujcky(Vypujcky vypujcky){
this.vypujcky = vypujcky;
}
public void setRegistr(Registr registr){
this.registr = registr;
}
}
Dependency Injection
Takzvaná Dependency Injection je speciální případ Inversion of Control (IoC generický termín) a řeší vlastní způsob vložení (spojení) potřebných objektů. Existují tři základní způsoby vložení.
- Setter injection
- Vložení se provádí pomocí klasických setteru, čili setovacích metod známých například z modelu JavaBean. Toto je jedna z možností, kterou poskytuje framework Spring.
- Constructor injection
- Vložení se provádí přes konstruktor, používá ji framework PicoKontejner (Spring opět podporuje).
- Interface injection
- Vložení se provádí skrze definované rozhraní, typickým představitelem je framework Avalon.
Diskuse se točí kolem toho, jaký způsob zvolit. Injekce skrze rozhraní stojí trošku na okraji a tak se především diskutuje, jestli je lepší použít settery nebo konstruktor. Constructor injection dovoluje jednoduše vyžadovat, aby byla implementace rozhraní nastavena při konstrukci vlastního objektu.
public class Knihovna implements VypujceneKnihy{
private Vypujcky vypujcky;
private Registr registr;
public Knihovna(Vypujcky vypujcky, Registr registr){
this.vypujcky = vypujcky;
this.registr = registr;
}
public List getSeznamVypujcenychKnih(Date obdobi){
//prace s objketem vypujcky a registr
}
}
Setter injection má obecně menší dopad na kód v případě, že běží mimo IoC kontejner (typicky pro unit testy). Nevýhodou je, že je možné vytvořit instanci třídy bez nastavení závislostí.
Odkazy a zdroje
- Introduction to Spring framework – Rod Johnson (TheServerSide, květen 2005)
- Expert One-on-One J2EE Development without EJB – Rod Johnson, Juergen Hoeller (Wrox, ISBN:0764558315)
- Inversion of Control Kontejners and the Dependency Injection pattern – Martin Fowler (23. 4. 2004)
- POJO Application Frameworks: Spring Vs. EJB 3.0 – Michael Juntao Yuan (OnJava, 29. 6. 2005)
- Pro Spring: Spring and EJB – Learn how to use Spring with EJB applictions – Rob Harrop a Jan Machacek (JavaWorld, 14. 2. 2005)
- Spring – Java/J2EE Application Framework Reference Documentation 1.2.x
- Spring in Action – Craig Walls, Ryan Breidenbach (Manning, ISBN:1932394354)
(Pozn. aut.: Za odbornou korekturu děkuji Janu Macháčkovi, spoluautorovi knihy Pro Spring.)
Starší komentáře ke článku
Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.
Mohlo by vás také zajímat
-
Fandíme českým sportovcům a rozdáváme hosting ZDARMA!
26. července 2024 -
Thunderbolt 4 vs. OCuLink: Přišel čas na upgrade?
27. května 2024
Nejnovější
-
Výkonný a kompaktní: ASOME Max Studio s výjimečným poměrem cena/výkon
11. listopadu 2024 -
Šokující data od Microsoftu: Kyberútoky rostou o stovky procent!
8. listopadu 2024 -
Chcete jedinečnou doménu? Objevte koncovky FOOD, MEME a MUSIC!
7. listopadu 2024 -
OpenAI představilo novou funkci ChatGPT Search
6. listopadu 2024
Jirka
Bře 14, 2011 v 22:20možná by bylo lepší dávat vysvětlivky ke zkratkám (ikdyž jsou možná všeobecně známé) na začátku článku a ne až v půlce…