Úvod do modelu notifikácie udalostí v CDI 2.0

1. Prehľad

CDI (Contexts and Dependency Injection) je štandardný rámec pre injektovanie závislostí platformy Jakarta EE.

V tomto výučbe sa pozrieme na CDI 2.0 a na to, ako stavia na výkonnom, typovo bezpečnom injekčnom mechanizme CDI 1.x od pridanie vylepšeného, ​​plne funkčného modelu oznámenia udalostí.

2. Závislosti Maven

Na začiatok postavíme jednoduchý projekt Maven.

Potrebujeme kontajner kompatibilný s CDI 2.0 a Weld, referenčná implementácia CDI, sa hodí:

  javax.enterprise cdi-api 2.0.SP1 org.jboss.weld.se weld-se-core 3.0.5. 

Ako obvykle môžeme sťahovať najnovšie verzie servera cdi-api a zvar-se-jadro z Maven Central.

3. Pozorovanie a zvládnutie vlastných udalostí

Jednoducho povedané, model notifikácie udalostí CDI 2.0 je klasickou implementáciou vzoru Observer, založený na @ Pozoruje anotácia parameter-parameter. Preto nám umožňuje ľahko definovať pozorovateľské metódy, ktoré je možné automaticky vyvolať v reakcii na jednu alebo viac udalostí.

Napríklad by sme mohli definovať jednu alebo viac fazúľ, ktoré by spustili jednu alebo viac konkrétnych udalostí, zatiaľ čo iné fazule by boli o udalostiach informované a podľa toho by reagovali.

Aby sme jasnejšie demonštrovali, ako to funguje, zostavíme jednoduchý príklad vrátane triedy základnej služby, triedy vlastných udalostí a metódy pozorovateľa, ktorá reaguje na naše vlastné udalosti.

3.1. Trieda základnej služby

Začnime vytvorením jednoduchého Textová služba trieda:

public class TextService {public String parseText (String text) {return text.toUpperCase (); }} 

3.2. Trieda vlastnej udalosti

Ďalej definujeme vzorovú triedu udalostí, ktorá zaberá a String argument v jeho konštruktore:

verejná trieda ExampleEvent {private final String eventMessage; public ExampleEvent (String eventMessage) {this.eventMessage = eventMessage; } // getter}

3.3. Definovanie metódy pozorovateľa pomocou @ Pozoruje Anotácia

Teraz, keď sme definovali naše triedy služieb a udalostí, použijeme @ Pozoruje anotácie, aby sme vytvorili metódu pozorovateľa pre našu ExampleEvent trieda:

verejná trieda ExampleEventObserver {public String onEvent (@Observes ExampleEvent event, TextService textService) {return textService.parseText (event.getEventMessage ()); }}

Zatiaľ čo na prvý pohľad je implementácia onEvent () metóda vyzerá dosť triviálne, v skutočnosti obsahuje veľa funkcií prostredníctvom @ Pozoruje anotácia.

Ako vidíme, onEvent () method je obsluha udalosti, ktorá trvá ExampleEvent a Textová služba objekty ako argumenty.

Nezabudnite, že všetky argumenty uvedené po @ Pozoruje anotácia sú štandardné injekčné body. Výsledkom bude, že CDI pre nás vytvorí plne inicializované inštancie a vloží ich do metódy pozorovateľa.

3.4. Inicializuje sa náš kontajner CDI 2.0

V tomto okamihu sme vytvorili naše triedy služieb a udalostí a definovali sme jednoduchú metódu pozorovateľa, ktorá reaguje na naše udalosti. Ako však môžeme nariadiť CDI, aby tieto prípady vložil za behu?

Tu ukazuje model upozornení na udalosti svoju funkčnosť naplno. Nové jednoducho inicializujeme SeContainer implementácia a spustenie jednej alebo viacerých udalostí prostredníctvom fireEvent () metóda:

SeContainerInitializer containerInitializer = SeContainerInitializer.newInstance (); try (SeContainer container = containerInitializer.initialize ()) {container.getBeanManager (). fireEvent (new ExampleEvent ("Welcome to Baeldung!")); }

Upozorňujeme, že používame SeContainerInitializer a SeContainer objekty, pretože CDI používame v prostredí Java SE, a nie v Jakarte EE.

Všetky pripojené metódy pozorovania budú oznámené, keď ExampleEvent je vyhodený šírením samotnej udalosti.

Pretože všetky objekty prešli ako argumenty po @ Pozoruje anotácia bude úplne inicializovaná, o zapojenie celého sa postará spoločnosť CDI Textová služba objektový graf pre nás, skôr ako ho vložíte do onEvent () metóda.

Stručne, máme výhody typovo bezpečného kontajnera IoC spolu s modelom oznámení udalostí bohatým na funkcie.

4. The ContainerInitialized Udalosť

V predchádzajúcom príklade sme použili vlastnú udalosť na odovzdanie udalosti metóde pozorovateľa a na získanie úplnej inicializácie Textová služba objekt.

To je samozrejme užitočné, keď skutočne potrebujeme šíriť jednu alebo viac udalostí vo viacerých bodoch našej aplikácie.

Niekedy jednoducho potrebujeme získať veľa plne inicializovaných objektov, ktoré sú pripravené na použitie v rámci našich tried aplikácií, bez toho, aby ste museli prejsť realizáciou ďalších udalostí.

Do tohto konca, CDI 2.0 poskytuje ContainerInitialized trieda udalostí, ktorá sa automaticky spustí pri inicializácii kontajnera Weld.

Poďme sa pozrieť na to, ako môžeme použiť ContainerInitialized udalosť na prenos kontroly do ExampleEventObserver trieda:

verejná trieda ExampleEventObserver {public String onEvent (@Observes ContainerInitialized event, TextService textService) {return textService.parseText (event.getEventMessage ()); }} 

A pamätaj na to the ContainerInitialized trieda udalosti je špecifická pre zváranie. Ak teda použijeme inú implementáciu CDI, budeme musieť refaktorovať naše metódy pozorovateľov.

5. Metódy podmieneného pozorovateľa

Pri jeho súčasnej implementácii náš ExampleEventObserver trieda štandardne definuje bezpodmienečnú metódu pozorovateľa. To znamená, že pozorovateľská metóda bude vždy informovaná o dodanej udalosti, bez ohľadu na to, či v aktuálnom kontexte inštancia triedy existuje alebo nie.

Rovnako môžeme definovať metódu podmieneného pozorovateľa upresnením notifyObserver = IF_EXISTS ako argument pre @ Pozoruje anotácia:

public String onEvent (@Observes (notifyObserver = IF_EXISTS) ExampleEvent event, TextService textService) {return textService.parseText (event.getEventMessage ()); } 

Keď použijeme metódu podmieneného pozorovateľa, metóda bude informovaná o zhodnej udalosti, iba ak v aktuálnom kontexte existuje inštancia triedy, ktorá definuje metódu pozorovateľa..

6. Metódy transakčných pozorovateľov

Môžeme tiež spustiť udalosti v rámci transakcie, napríklad aktualizáciu alebo odstránenie databázy. Za týmto účelom môžeme definovať metódy transakčných pozorovateľov pridaním znaku počas argument k @ Pozoruje anotácia.

Každá možná hodnota počas argument zodpovedá konkrétnej fáze transakcie:

  • BEFORE_COMPLETION
  • AFTER_COMPLETION
  • AFTER_SUCCESS
  • AFTER_FAILURE

Ak vypálime ExampleEvent udalosť v rámci transakcie, musíme refaktorovať onEvent () zodpovedajúcim spôsobom zvládnuť udalosť počas požadovanej fázy:

public String onEvent (@Observes (during = AFTER_COMPLETION) ExampleEvent event, TextService textService) {return textService.parseText (event.getEventMessage ()); }

Metóda transakčného pozorovateľa bude informovaná o dodanej udalosti až vo fáze párovania danej transakcie.

7. Objednávanie metód pozorovateľa

Ďalším príjemným vylepšením, ktoré je súčasťou modelu notifikácie udalostí CDI 2.0, je schopnosť nastavenia zoradenia alebo priority pre volanie pozorovateľov danej udalosti.

Poradie, v akom sa budú metódy pozorovateľov volať, môžeme ľahko určiť zadaním @ Priorita anotácia po @ Pozoruje.

Aby sme pochopili, ako táto funkcia funguje, definujeme inú metódu pozorovateľa, okrem tej, ktorá ExampleEventObserver realizuje:

verejná trieda AnotherExampleEventObserver {public String onEvent (@Observes ExampleEvent event) {return event.getEventMessage (); }}

V takom prípade budú mať obe metódy pozorovateľa predvolene rovnakú prioritu. Poradie, v akom ich CDI vyvolá, je teda jednoducho nepredvídateľné.

Ľahko to napravíme tak, že každej metóde pridelíme prioritu vyvolania prostredníctvom @ Priorita anotácia:

public String onEvent (@Observes @Priority (1) ExampleEvent event, TextService textService) {// ... implementation} 
public String onEvent (@Observes @Priority (2) ExampleEvent event) {// ... implementácia}

Úrovne priority sa riadia prirodzeným usporiadaním. Preto CDI najskôr zavolá metódu pozorovateľa s úrovňou priority 1 a vyvolá druhú metódu s úrovňou priority 2.

Podobne, ak použijeme rovnakú úroveň priority vo dvoch alebo viacerých metódach, poradie je opäť nedefinované.

8. Asynchrónne udalosti

Vo všetkých príkladoch, ktoré sme sa doteraz dozvedeli, sme udalosti spúšťali synchronne. CDI 2.0 nám však umožňuje ľahko spúšťať aj asynchrónne udalosti. Metódy asynchrónneho pozorovateľa potom môžu spracovávať tieto asynchrónne udalosti v rôznych vláknach.

Môžeme vystreliť udalosť asynchrónne s fireAsync () metóda:

verejná trieda ExampleEventSource {@Inject Event exampleEvent; public void fireEvent () {exampleEvent.fireAsync (nový ExampleEvent ("Vitajte v Baeldungu!")); }}

Fazuľa spúšťa udalosti, ktoré sú implementáciou Udalosť rozhranie. Preto ich môžeme injekčne podať ako ktorúkoľvek inú konvenčnú fazuľu.

Aby sme zvládli našu asynchrónnu udalosť, musíme definovať jednu alebo viac metód asynchrónneho pozorovateľa pomocou @ObservesAsync anotácia:

verejná trieda AsynchronousExampleEventObserver {public void onEvent (@ObservesAsync ExampleEvent event) {// ... implementácia}}

9. Záver

V tomto článku naučili sme sa, ako začať používať vylepšený model oznamovania udalostí dodávaný s CDI 2.0.

Ako obvykle sú všetky ukážky kódu zobrazené v tomto tutoriáli dostupné na GitHub.


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