Myšlenky dne otce Fura

Dává je jen zřídka, obvykle jim není moc rozumět a často vám ani k ničemu nejsou.

Část #1: Modulární systémy ve Spring Frameworku

Autor Otec Fura, publikováno dne 14.9.2007
Publikováno k: Spring Framework. 1 komenář

V tomto díle si povíme něco o aplikačních kontextech, jejich vlastnostech a možnosti jejich řetězení do stromové struktury. Tato část je základem principem celého modulární skladby, jejíž detaily vám budu v následujících dílech popisovat. Jak jsem již uváděl v předmluvě, nejedná se o nic světoborného, jen o základní principy Springu.

Aplikační kontexty

Celý Spring je postaven na aplikačních kontextech. Aplikační kontext se dá nejlépe přiblížit ke class loaderům v Javě, má i řadu podobných vlastností. Aplikační kontexty mohou tvořit strom, kontexty v nižších úrovních se odkazují na kontexty nadřazené. Z nižších kontextů jsou viditelné beany v kontextech nadřazených, z nižších kontextů jsou ApplicationEventy posílány ke zpracování i do nadřazených kontextů. Pouze post processorové faktory (BeanPostProcessor a BeanFactoryPostProcessor) jsou pro každý kontext definovány zvlášť.

Aplikační kontext je něco víc jak BeanFactory – krom jiného se stará o:

  • inicializaci Multicasteru (ten se stará o distribuci událostí), buď defaultním objektem SimpleApplicationEventMulticaster nebo vámi definovaným objektem, který je nalezen v konfiguraci pod názvem „applicationEventMulticaster“
  • automatické nalezení bean ApplicationListenerů v konfiguraci a jejich zaregistrování do Multicasteru
  • zaregistruje JVM shutdown hook, na který se můžete navěsit v případě, že chcete uvolnit nějaké zdroje, pokud je zvenčí vyvoláno ukončení JVM
  • postprocessing vašich bean – konkrétně splnění kontraktů rozhraní ApplicationContextAware, ApplicationContextAwareProcessor, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware
  • poskytuje podporu pro AOP

Dokumentace Springu mluví rozdílech aplikačního kontextu a bean factory takto:

„Users are sometimes unsure whether a BeanFactory or an ApplicationContext is best suited for use in a particular situation. A BeanFactory pretty much just instantiates and configures beans. An ApplicationContext also does that, and it provides the supporting infrastructure to enable lots of enterprise-specific features such as transactions and AOP.“

V celé řadě případů si vystačíte pouze s jedním hlavním aplikačním kontextem. Někdy však můžete zcela nevědomky používat dva – například Springový plugin do Strutsů funguje tak, že pro každý Strutsový modul vytváří vlastní aplikační kontext s definicí action bean a navěšuje jej na hlavní WebApplicationContext uložený v ServletContextu (viz. metoda: createWebApplicationContext třídy ContextLoaderPlugIn).

Také WebApplicationContext nemusí být tím hlavním. Pokud do web.xml do init parametru přidáte parametr s názvem „parentContextKey“ a jako hodnotu doplníte klíč pod kterým se v BeanFactoryLocator nalézá jiný aplikační kontext, bude tento aplikační kontext dosazen jako parent kontext toho webového (viz. třída ContextLoader, metoda loadParentContext). Dosadit parent kontext pro web aplikační kontext můžete také velmi jednoduše přepsáním této třídy a předefinováním metody loadParentContext.

Kouzlo řetězení Spring aplikačních kontextů

Řetězení aplikačních kontextů můžeme použít k oddělení kontextů jednotlivých částí aplikace s možností vysdílet jejich společné části. Představte si, že vyvíjíte dvě aplikační knihovny, které spolu co se týče business logiky nijak nesouvisí – například nějaká reportovací knihovna a knihovna pro správu uživatelů. Obě dvě knihovny se vyvíjejí nezávisle a obě jsou postavené na Springu. Pak máte nějakou web aplikaci, ve které chcete oba „moduly“ využít. Vzhledem k tomu, že oba moduly byly vyvíjeny nezávisle, může se jednoduše stát, že budou mít některé beany stejné názvy a při startu by vám Spring vyhořel (a je ještě řada dalších věcí, které by mohly způsobit problémy).

Ideální by bylo umožnit oběma modulům žít dále ve svých oddělených aplikačních kontextech. Co však s beanami, které bychom chtěli mít společné? Stačí nám k tomu definovat rootovský aplikační kontext, který bude obsahovat definici společných bean a oběma modulům nastavit tento „root“ kontext jako jejich parent kontext.

Pozn.: společnými beanami jsou myšleny např. MailSender, DataSource, TransactionManager a podobné beany, které potřebuje ke svému chodu každý modul (nebo alespoň větší část modulů) a které chceme zároveň konfigurovat a mít pouze jednou v celé aplikaci.

Z jednotlivých modulů se vyjmou deklarace sdílených bean a přesunou se do extra konfiguračního souboru, který využijeme pouze pro testy. V reálné aplikaci tyto beany vždy dostaneme „svrchu“ od root aplikačního kontextu. Pokud bychom narazili na problém rozdílného pojmenování sdílených bean v root kontextu oproti názvům, které očekává modul, můžeme jednoduše aliasem vytvořit beanu s potřebným názvem pro konkrétní modul.

Tuto kompozici používá například open source Flash server Red5 a nyní i CMS FG Forrest ;-) .

Jak inicializovat root context

Root context je typicky singletonem – ukládáme jej do statické proměnné a existuje pouze jednou v celé aplikaci. Je to obdobná strategie, kterou používá ContextSingletonBeanFactoryLocator, který bychom mohli k této operaci využít. Pro vlastní inicializaci je asi nejvhodnější statický konstruktor. Pro inspiraci uvádím příklad kódu:

public class RootContextLocator {
     private static ApplicationContext rootContext;

     static {
          //ve statickém konstruktoru inicializujeme konfiguraci
          rootContext = new ClasspathXmlApplicationContext("classpath:META-INF/rootApplicationContext.xml");
     }

     public static ApplicationContext getRootApplicationContext() {
          return rootContext;
     }

}

Kdekoliv v aplikaci je pak možné díky statické metodě získat přístup k root kontextu. Existence jediné instance tohoto kontextu je zajištěna právě statickým konstruktorem třídy RootContextLocator.

Root kontext bude obvykle poměrně hubený – bude obsahovat jen pár společných bean. S postupem času si ukážeme, že hlavním cílem root kontextu je, stát se jakousi postavou ve středu dění (z anglického „man in the middle“ ;-) ), která se stará především o koordinaci podřízených kontextů a sloužící k jejich vzájemnému propojení.

Použití v J2EE

Tímto způsobem můžeme také vytvořit root kontext, který bude jedinečný (společný) pro různé web aplikace i EJB v rámci jednoho EARu. V případě, že bude RootContextLocator třída nahrávaná EAR root classloaderem (více o classloaderech v J2EE) a můžeme tedy sdílet základní beany i mezi různými web aplikacemi a EJB.

V souvislosti s J2EE připomínám, že aplikační servery mohou používat více JVM pro stejný EAR. V takovém případě bude root kontext fyzicky vícekrát (to je ostatně společný problém všech singletonů v J2EE prostředí) a proto je třeba tento fakt brát v úvahu. Což tedy znamená, že stavové informace je vhodné ukládat do bean, o jejich replikaci se nám aplikační server postará (např. beany uložené v session) nebo si takové údaje ukládat např. do databáze a držet se spíše stateless bean (myšleno Spring bean).

Další věcí, kterou je dobré si uvědomit, že v J2EE v podstatě nesmíte skoro nic. O propagaci datasourců a dalších věcí do web aplikací a EJB se stará sám kontejner a asi by nebylo nejvhodnější se mu plést do práce paralelním pašováním datasourcu z root spring kontextu (osobně si myslím, že ten by se ani k datasourcu v JNDI při inicializaci ještě ani nemohl dostat).

Upozorňuji, že v J2EE nejsem kovaný, takže pokud byste se hodlali pouštět do něčeho podobného, ověřte si chování na nějakém prototypu.

Každopádně podobnou architekturu už si vyzkoušeli ve zmíněném Red5 serveru – viz. mail jednoho z vývojářů.

Co bude v další části seriálu?!

V další části seriálu bude rozebrána problematika refreshe stromu aplikačních kontextů. Toto je skvělá vlastnost Springu, která je často nedoceněná a málo používaná. Díky ní je možné jednoduše zahodit všechny současné instance bean definované v aplikačním kontextu a provést kompletní reinicalizaci kontextu s aktuální konfigurací (tak můžeme elegantně změnit chování aplikace bez nutnosti restartu serveru). S refreshem aplikačního kontextu se dá vyřešit poměrně dost věcí i v produkčním prostředí – navíc netrpí problémem PermGenSpace jako při reloadu kontextu celé aplikace na serveru. V situaci, kdy máme ale celý strom aplikačních kontextů se nám situace poměrně komplikuje – refresh se totiž stromem sám od sebe nezpropaguje.

Díl #2: Refresh stromu aplikačních kontextů

Líbilo se ti? Sdílej:

  • Google +1
  • Facebook
  • Twitter
  • Email
  • More
  • Digg
  • StumbleUpon

Související články:

  1. Část #2: Modulární systémy ve Spring Frameworku
    V této části seriálu si rozebereme problematiku refreshe stromu aplikačních kontextů. Toto je skvělá vlastnost Springu, která je často nedoceněná a málo používaná. Díky ní je možné jednoduše zahodit všechny...V této části seriálu si rozebereme problematiku refreshe stromu aplikačních kontextů. Toto je skvělá vlastnost Springu, která je často nedoceněná a málo používaná. Díky ní je [...]...
  2. Část #3: Modulární systémy ve Spring Framework
    V prvním díle jsme si ukázali, jak jednotlivé moduly separovat a propojit ve stromu. V předchozím pak způsob, jak strom udržet konzistentní a refreshovatelný za běhu aplikace. Dnešní díl bude...V prvním díle jsme si ukázali, jak jednotlivé moduly separovat a propojit ve stromu. V předchozím pak způsob, jak strom udržet konzistentní a refreshovatelný za běhu [...]...
  3. Seriál: Modulární systémy ve Spring Frameworku
    Ve chvíli, kdy začnete používat při vývoji masivněji Spring Framework a začnete vytvářet znovupoužitelné knihovny postavené nad tímto frameworkem, začnete řešit jak z těchto knihoven co nejlépe složit výslednou aplikaci....Ve chvíli, kdy začnete používat při vývoji masivněji Spring Framework a začnete vytvářet znovupoužitelné knihovny postavené nad tímto frameworkem, začnete řešit jak z těchto knihoven co [...]...
  4. Část #4: Modulární systémy ve Spring Framework
    Aplikační události jsou jedním ze základních stavebních kamenů Springu a proto by bylo škoda se ochudit o tuto skvělou vlastnost na rozhraní modulů. Je zřejmé, že nebudeme chtít otevřít všechny...Aplikační události jsou jedním ze základních stavebních kamenů Springu a proto by bylo škoda se ochudit o tuto skvělou vlastnost na rozhraní modulů. Je zřejmé, že [...]...
  5. Spring AOP – Pozor na AspectJExpressionPointcut!
    Tento týden jsem řešil problém s nedostatkem paměti při spouštění testů jednoho projektu. Pro běh testů nestačilo výchozích 64MB paměti Javy na heapu, což mi připadlo v porovnání s velikostí...Tento týden jsem řešil problém s nedostatkem paměti při spouštění testů jednoho projektu. Pro běh testů nestačilo výchozích 64MB paměti Javy na heapu, což mi připadlo [...]...

Navigace mezi články

← Seriál: Modulární systémy ve Spring Frameworku
Část #2: Modulární systémy ve Spring Frameworku →

Napsat komentář Zrušit odpověď na komentář

  • Vyhledávání

  • Poslední komentáře

    • DevFest Pardubice 2013 (6)
      • Podle organizátorů by měly být přednášky online nejpozději do prázdnin a toto oznámí skrz standardní kanály – tj....
      • Zjišťuju u organizátorů. Jakmile se něco dozvím, napíšu to sem. #stayTuned
      • existuju k jednotlivym prednaskam video podcasty? ze by som si ich aspon doma takto popozeral ak ano kde ich mozem...
      • Díky za upozornění – ta věta byla špatně formulovaná (již jsem napravil). Chtěl jsem říci, první PARDUBICKÝ...
      • Díky za reportáž. Na přednášky asi nebude čas, ale beru to aspoň jako upozornění na zajímavé projekty.
  • @Novoj

    My Tweets
  • Přepnout zobrazení

    • Přepnout do mobilního zobrazení
  • Články které nestárnou

    • Cesta k legalitě
    • O tomto blogu …
    • Poznámky k instalaci Ubuntu
    • První rok Myšlenek Otce Fura
    • Druhý rok Myšlenek Otce Fura
    • Třetí rok Myšlenek Otce Fura
    • Čtvrtý rok Myšlenek Otce Fura
    • Pátý rok Myšlenek Otce Fura
    • Šestý rok Myšlenek Otce Fura
  • Kategorie

    • Android (2)
    • English (12)
    • Nezařazené (14)
    • Podcast (16)
    • Programování (119)
      • Bezpečnost (3)
      • Databáze (7)
      • Groovy (3)
      • iBatis (7)
      • Java (80)
      • JavaScript (7)
      • Management (1)
      • Spring Framework (24)
      • Stripes (2)
      • Testování (18)
      • User Experience (1)
      • Úvahy (5)
      • Web (19)
    • Reportáže (27)
      • DevFest (1)
      • GeeCON (5)
      • Hackathon (3)
      • jOpenSpace (9)
      • WebExpo (3)
    • Softwarové nástroje (22)
      • IntelliJ Idea (5)
      • Maven (9)
      • Selenium (2)
      • TeamCity (1)
  • Zobrazit na mobilu

    QR Code - scan to visit our mobile site
  • Moje vývěska

    JetBrains Academy Member Tento blog čte:

    Můj profil:
    View Jan Novotny's profile on LinkedIn
    Passionate aboutIDE for professional JavaScript
    development with AJAX ready refactorings
    stopsoftwarepatents.eu petition banner
  • Reklama

  • Odkazy

    • FG Forrest
    • Flavors.me
    • Profesní životopis
    • Šermírna
    • SHŠ Rabidus
  • Podcasty

    • CZ Podcast
    • Freakonomics
    • JavaPosse
    • Software Radio Engeneering
  • Portály

    • InfoQ
    • Java Open Source
    • Java.cz
    • OnJava
    • The Server Side
  • Sledované blogy

    • Blog o Javičce
    • DagBlog
    • Java drobečky
    • Lukáš Vlček
    • Rubicon
    • SoftEu
    • Všeho s Mírou
  • Licence

    Licence Creative CommonsČlánky z blogu Myšlenky dne Otce Fura, jejímž autorem je Ing. Jan Novotný, podléhá licenci Creative Commons Uveďte autora 3.0 Unported .

    Vytvořeno na základě tohoto díla: blog.novoj.net
Proudly powered by WordPress Šablona: Parament od Automattic.

With Google+ plugin by Geoff Janes

Přepnout do mobilního zobrazení

loading Zrušit
Post was not sent - check your email addresses!
Email check failed, please try again
Sorry, your blog cannot share posts by email.