Vlastný rozsah na jar

1. Prehľad

Po vybalení z krabice ponúka Spring dva štandardné rozsahy fazule („Singleton“ a „Prototyp“), ktoré je možné použiť v ktorejkoľvek aplikácii Spring, plus tri ďalšie rozsahy fazule („Žiadosť“, „Relácia“a „GlobalSession“) na použitie iba vo webových aplikáciách.

Štandardné rozsahy fazule nemožno prepísať a všeobecne sa považuje za zlý postup prepísať rozsahy vedomé o webe. Môžete však mať aplikáciu, ktorá vyžaduje iné alebo ďalšie schopnosti, ako sú možnosti uvedené v uvedených rozsahoch.

Napríklad, ak vyvíjate systém s viacerými nájomníkmi, môžete poskytnúť samostatnú inštanciu konkrétnej fazule alebo sady bôbov pre každého nájomcu. Jar poskytuje mechanizmus na vytváranie vlastných rozsahov pre scenáre, ako je tento.

V tomto rýchlom návode si ukážeme ako vytvoriť, zaregistrovať a použiť vlastný rozsah v jarnej aplikácii.

2. Vytvorenie triedy vlastného rozsahu

Ak chcete vytvoriť vlastný rozsah, musíme implementovať Rozsah rozhranie. Pritom musíme tiež zabezpečiť, aby implementácia bola bezpečná pre všetky vlákna pretože rozsahy môžu používať viaceré továrne na výrobu fazúľ súčasne.

2.1. Správa obmedzených objektov a spätných volaní

Jedna z prvých vecí, ktoré je potrebné zohľadniť pri implementácii zvyku Rozsah trieda je spôsob, akým budete ukladať a spravovať obmedzené objekty a spätné volania ničenia. To by sa dalo urobiť napríklad pomocou mapy alebo vyhradenej triedy.

V tomto článku to urobíme spôsobom bezpečným pre vlákna pomocou synchronizovaných máp.

Začnime definovať našu vlastnú triedu rozsahu:

verejná trieda TenantScope implementuje Scope {private Map scopedObjects = Collections.synchronizedMap (new HashMap ()); private Map destruCallbacks = Collections.synchronizedMap (new HashMap ()); ...}

2.2. Získanie objektu z rozsahu

Ak chcete z nášho rozsahu načítať objekt podľa názvu, implementujme getObject metóda. Ako uvádza JavaDoc, ak pomenovaný objekt v rozsahu neexistuje, musí táto metóda vytvoriť a vrátiť nový objekt.

Pri našej implementácii kontrolujeme, či je pomenovaný objekt na našej mape. Ak je, vrátime ho a ak nie, použijeme ObjectFactory Ak chcete vytvoriť nový objekt, pridajte ho na našu mapu a vráťte ho:

@Override public Object get (názov reťazca, ObjectFactory objectFactory) {if (! ScopedObjects.containsKey (name)) {scopedObjects.put (name, objectFactory.getObject ()); } návrat scopedObjects.get (meno); }

Z piatich metód definovaných v Rozsah rozhranie, len dostať úplná implementácia vyžaduje metódu opísaného správania. Ďalšie štyri metódy sú voliteľné a môžu sa hodiť UnsupportedOperationException ak nepotrebujú alebo nemôžu podporovať funkciu.

2.3. Registrácia spätného volania na zničenie

Musíme tiež implementovať registerDestructionCallback metóda. Táto metóda poskytuje spätné volanie, ktoré sa má vykonať, keď je pomenovaný objekt zničený alebo ak je samotný rozsah zničený aplikáciou:

@Override public void registerDestructionCallback (názov reťazca, spustiteľné spätné volanie) {destruCallbacks.put (meno, spätné volanie); }

2.4. Odstránenie objektu z rozsahu

Ďalej poďme implementovať odstrániť metóda, ktorá odstráni pomenovaný objekt z rozsahu a tiež odstráni jeho spätné volanie registrovaného zničenia a vráti odstránený objekt:

@Override public Object remove (Názov reťazca) {destruCallbacks.remove (meno); return scopedObjects.remove (meno); }

Poznač si to je zodpovednosťou volajúceho skutočne vykonať spätné volanie a zničiť odstránený objekt.

2.5. Získanie ID konverzácie

Teraz poďme implementovať getConversationId metóda. Ak váš obor podporuje koncept ID konverzácie, vrátili by ste ho sem. V opačnom prípade sa má dohovor vrátiť nulový:

@Override public String getConversationId () {return "tenant"; }

2.6. Riešenie kontextových objektov

Nakoniec poďme implementovať resolveContextualObject metóda. Ak váš rozsah podporuje viac kontextových objektov, každý z nich spojíte s kľúčovou hodnotou a vrátite objekt zodpovedajúci zadanej hodnote kľúč parameter. V opačnom prípade sa má dohovor vrátiť nulový:

@Override public Object resolveContextualObject (reťazcový kľúč) {return null; }

3. Registrácia vlastného rozsahu

Ak chcete, aby si kontajner Spring uvedomil váš nový rozsah, musíte zaregistrujte to cez registerScope metóda na a ConfigurableBeanFactory inštancia. Pozrime sa na definíciu tejto metódy:

void registerScope (String scopeName, Scope scope);

Prvý parameter, scopeName, sa používa na identifikáciu / špecifikáciu rozsahu podľa jeho jedinečného názvu. Druhý parameter, rozsah, je skutočnou inštanciou zvyku Rozsah implementáciu, ktorú chcete zaregistrovať a používať.

Vytvorme si zvyk BeanFactoryPostProcessor a zaregistrujte náš vlastný rozsah pomocou a ConfigurableListableBeanFactory:

verejná trieda TenantBeanFactoryPostProcessor implementuje BeanFactoryPostProcessor {@Override public void postProcessBeanFactory (ConfigurableListableBeanFactory factory) hodí BeansException {factory.registerScope ("tenant", new TenantScope ()); }}

Poďme teraz napísať triedu jarnej konfigurácie, ktorá načíta našu BeanFactoryPostProcessor implementácia:

@Configuration public class TenantScopeConfig {@Bean public static BeanFactoryPostProcessor beanFactoryPostProcessor () {return new TenantBeanFactoryPostProcessor (); }}

4. Používanie vlastného rozsahu

Teraz, keď sme zaregistrovali náš vlastný rozsah, môžeme ho použiť na ktorúkoľvek z našich fazúľ, rovnako ako na akýkoľvek iný fazuľa, ktorá používa iný rozsah ako singleton (predvolený rozsah) - pomocou @Rozsah anotáciu a špecifikáciu nášho vlastného rozsahu podľa názvu.

Vytvorme jednoduchý TenantBean trieda - o chvíľu deklarujeme fazuľa tohto typu s rozsahom nájomcu:

verejná trieda TenantBean {súkromné ​​konečné meno reťazca; public TenantBean (názov reťazca) {this.name = meno; } public void sayHello () {System.out.println (String.format ("Dobrý deň od% s typu% s", this.name, this.getClass (). getName ())); }}

Upozorňujeme, že sme nepoužili úroveň triedy @ Komponent a @Rozsah anotácie k tejto triede.

Poďme si teraz v konfiguračnej triede definovať niektoré fazule s rozsahom nájomcu:

@Configuration public class TenantBeansConfig {@Scope (scopeName = "tenant") @Bean public TenantBean foo () {return new TenantBean ("foo"); } @Scope (scopeName = "tenant") @Bean public TenantBean bar () {return new TenantBean ("bar"); }}

5. Testovanie vlastného rozsahu

Poďme napísať test, ktorý preverí našu vlastnú konfiguráciu rozsahu načítaním súboru ApplicationContext, registrácia našich Konfigurácia triedy a získanie našich fazúľ s rozsahom nájomcu:

@Test public final void whenRegisterScopeAndBeans_thenContextContainsFooAndBar () {AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext (); try {ctx.register (TenantScopeConfig.class); ctx.register (TenantBeansConfig.class); ctx.refresh (); TenantBean foo = (TenantBean) ctx.getBean ("foo", TenantBean.class); foo.sayHello (); TenantBean bar = (TenantBean) ctx.getBean ("bar", TenantBean.class); bar.sayHello (); Map foos = ctx.getBeansOfType (TenantBean.class); assertThat (foo, not (equalTo (bar))); assertThat (foos.size (), equalTo (2)); assertTrue (foos.containsValue (foo)); assertTrue (foos.containsValue (bar)); BeanDefinition fooDefinition = ctx.getBeanDefinition ("foo"); BeanDefinition barDefinition = ctx.getBeanDefinition ("bar"); assertThat (fooDefinition.getScope (), equalTo ("tenant")); assertThat (barDefinition.getScope (), equalTo ("tenant")); } nakoniec {ctx.close (); }}

A výstup z nášho testu je:

Ahoj z foo typu org.baeldung.customscope.TenantBean Ahoj z pruhu typu org.baeldung.customscope.TenantBean

6. Záver

V tomto rýchlom výučbe sme si ukázali, ako na jar definovať, zaregistrovať a používať vlastný rozsah.

Viac informácií o vlastných rozsahoch si môžete prečítať v Spring Framework Reference. Môžete sa tiež pozrieť na jarné implementácie rôznych Rozsah triedy v úložisku Spring Framework na GitHub.

Ako obvykle nájdete ukážky kódu použité v tomto článku v projekte GitHub.


$config[zx-auto] not found$config[zx-overlay] not found