Tavaszi események

1. Áttekintés

Ebben a cikkben megvitatjuk hogyan kell használni a tavaszi eseményeket.

Az események a keret egyik figyelmen kívül hagyott funkciója, de egyben hasznosabbak is. És - mint sok más dolog tavasszal - az eseménykiadás is az egyik képesség, amelyet nyújt ApplicationContext.

Néhány egyszerű irányelv követendő:

  • az eseménynek ki kell terjednie ApplicationEvent
  • a kiadónak be kell adnia egy ApplicationEventPublisher tárgy
  • a hallgatónak végre kell hajtania a ApplicationListener felület

2. Egyedi esemény

A tavasz lehetővé teszi számunkra, hogy egyedi eseményeket hozzunk létre és tegyünk közzé, amelyek alapértelmezés szerint szinkron. Ennek van néhány előnye - például, hogy a hallgató részt vehet a kiadó tranzakciós kontextusában.

2.1. Egyszerű alkalmazási esemény

Teremtsünk egy egyszerű rendezvényóra - csak egy helyőrző az eseményadatok tárolására. Ebben az esetben az eseményosztály egy String üzenetet tartalmaz:

public class CustomSpringEvent kiterjeszti az ApplicationEvent {private String üzenetet; public CustomSpringEvent (Object source, String message) {szuper (forrás); this.message = üzenet; } public String getMessage () {return üzenet; }}

2.2. Kiadó

Most alkossunk az esemény kiadója. A kiadó elkészíti az eseményobjektumot és közzéteszi mindenkinek, aki hallgatja.

Az esemény közzétételéhez a kiadó egyszerűen beadhatja a ApplicationEventPublisher és használja a publishEvent () API:

@Component public class CustomSpringEventPublisher {@Autowired private ApplicationEventPublisher applicationEventPublisher; public void publishCustomEvent (utolsó karakterlánc üzenet) {System.out.println ("Egyéni esemény közzététele."); CustomSpringEvent customSpringEvent = új CustomSpringEvent (ez, üzenet); applicationEventPublisher.publishEvent (customSpringEvent); }}

Alternatív megoldásként a kiadói osztály megvalósíthatja a ApplicationEventPublisherAware interfész - ez az esemény megjelenítőjét is befecskendezi az alkalmazás indításakor. Általában egyszerűbb, ha csak injekciót ad a kiadónak @Autowire.

2.3. Hallgató

Végül hozzuk létre a hallgatót.

Az egyetlen követelmény a hallgató számára, hogy bab legyen és megvalósítsa ApplicationListener felület:

@Component public class CustomSpringEventListener implementálja az ApplicationListener {@Override public void onApplicationEvent (CustomSpringEvent event) {System.out.println ("Fogadott tavaszi egyéni esemény -" + event.getMessage ()); }}

Figyelje meg, hogyan van az egyéni figyelőnk paraméterezve az egyéni esemény általános típusával - ami a onApplicationEvent () módszer típusbiztonságos. Ezzel elkerülhető az is, hogy ellenőrizni kell, hogy az objektum egy adott eseményosztály példánya-e, és át kell önteni.

És mint már tárgyaltuk - alapértelmezés szerint a tavaszi események szinkronosak - a doStuffAndPublishAnEvent () A módszer addig blokkol, amíg az összes hallgató befejezi az esemény feldolgozását.

3. Aszinkron események létrehozása

Bizonyos esetekben az események szinkron közzététele valójában nem az, amit keresünk - szükségünk lehet eseményeink aszinkron kezelésére.

A konfigurációban ezt bekapcsolhatja egy ApplicationEventMulticaster bab egy végrehajtóval; céljainkra itt SimpleAsyncTaskExecutor jól működik:

@Configuration public class AsynchronousSpringEventsConfig {@Bean (name = "applicationEventMulticaster") public ApplicationEventMulticaster simpleApplicationEventMulticaster () {SimpleApplicationEventMulticaster eventMulticaster = new SimpleApplicationEventMulticaster (); eventMulticaster.setTaskExecutor (új SimpleAsyncTaskExecutor ()); visszatérési eseményMulticaster; }}

Az esemény, a kiadó és a hallgató megvalósításai ugyanazok maradnak, mint korábban - de most a hallgató aszinkron módon külön szálban fogja kezelni az eseményt.

4. Meglévő keretesemények

Maga a Spring különféle eseményeket tesz közzé a dobozból. Például a ApplicationContext kirúgja a különféle keretrendezvényeket. Például. ContextRefreshedEvent, ContextStartedEvent, RequestHandledEvent stb.

Ezek az események lehetőséget nyújtanak az alkalmazásfejlesztőknek arra, hogy bekapcsolódjanak az alkalmazás és a kontextus életciklusába, és szükség esetén hozzáadják saját egyéni logikájukat.

Itt van egy gyors példa arra, hogy a hallgató frissítéseket hallgat:

public class ContextRefreshedListener implementálja az ApplicationListener {@Override public void onApplicationEvent (ContextRefreshedEvent cse) {System.out.println ("A kontextus újrakezdő eseményének kezelése."); }}

Ha többet szeretne megtudni a meglévő keretrendezvényekről, tekintse meg a következő oktatóanyagunkat itt.

5. Kommentárvezérelt eseményfigyelő

A 4.2 tavasztól kezdve az eseményhallgatónak nem kell babnak lennie a ApplicationListener felület - bármelyikre regisztrálható nyilvános a kezelt bab módszere a @EventListener kommentár:

@Component public class AnnotationDrivenEventListener {@EventListener public void handleContextStart (ContextStartedEvent cse) {System.out.println ("A környezetkezelés elindított esemény."); }}

Az előzőekhez hasonlóan a metódus-aláírás is deklarálja az általa elfogyasztott eseménytípust.

Alapértelmezés szerint a hallgatót szinkron módon hívják meg. Azonban egy an hozzáadásával könnyen aszinkronvá tehetjük @Aszinkron annotáció. Emlékeznünk kell az engedélyezésre Async támogatás az alkalmazásban.

6. Generics támogatás

Az események generikus információkkal is elküldhetők az eseménytípusban.

6.1. Általános alkalmazásesemény

Hozzunk létre egy általános eseménytípust. Példánkban az esemény osztály tartalmaz bármilyen tartalmat és a siker állapotjelző:

public class GenericSpringEvent {private T what; védett logikai siker; public GenericSpringEvent (T mi, logikai siker) {ez.mi = mi; ez.siker = siker; } // ... standard getters}

Figyelje meg a különbséget GenericSpringEvent és CustomSpringEvent. Most már rugalmasan közzétehetünk bármilyen tetszőleges eseményt, és nem szükséges hosszabbítani ApplicationEvent többé.

6.2. Hallgató

Most alkossunk az esemény hallgatója. Megvalósítással definiálhatnánk a hallgatót az ApplicationListener felület, mint korábban:

@ Component public class GenericSpringEventListener implementálja az ApplicationListener alkalmazást {@Orride public void onApplicationEvent (@NonNull GenericSpringEvent event) {System.out.println ("Fogadott tavaszi általános esemény -" + event.getWhat ()); }}

De sajnos ez a meghatározás megköveteli tőlünk az öröklést GenericSpringEvent tól ApplicationEvent osztály. Tehát ehhez az oktatóanyaghoz használjunk egy annotáció által vezérelt eseményhallgatót, amelyet korábban tárgyaltunk.

Az is lehetséges tegye feltételessé az eseményfigyelőt logikai SpEL kifejezés definiálásával a @EventListener annotáció. Ebben az esetben az eseménykezelőt csak a siker érdekében hívják meg GenericSpringEvent nak,-nek Húr:

@Component public class AnnotationDrivenEventListener {@EventListener (condition = "# event.success") public void handleSuccessful (GenericSpringEvent event) {System.out.println ("Általános esemény kezelése (feltételes)."); }}

A Spring Expression Language (SpEL) egy erőteljes kifejezésnyelv, amelyet egy másik oktatóanyag részletesen tárgyal.

6.3. Kiadó

Az eseménykiadó hasonló a fent leírtakhoz. De a típusú törlés miatt közzé kell tennünk egy olyan eseményt, amely megoldja azt a generikus paramétert, amelyre szűrnénk. Például, osztály GenericStringSpringEvent kiterjeszti GenericSpringEvent.

És ott van az események publikálásának alternatív módja. Ha egy nullával nem null értéket adunk vissza egy - vel annotált módszerrel @EventListener ennek eredményeként a Spring Framework új eseményként küldi el nekünk ezt az eredményt. Sőt, több új eseményt is közzétehetünk, ha az események feldolgozása eredményeként visszaadjuk őket egy gyűjteménybe.

7. Tranzakcióval kötött események

Ez a bekezdés a @TransactionalEventListener annotáció. Ha többet szeretne megtudni a tranzakciók kezeléséről, tekintse meg a Tranzakciók tavasszal és a JPA oktatóanyagot.

A 4.2 tavasz óta a keretrendszer újat nyújt @TransactionalEventListener annotáció, amely a @EventListener, amely lehetővé teszi az esemény hallgatójának a tranzakció egy szakaszához való kötését. A kötés a következő tranzakciós fázisokra lehetséges:

  • AFTER_COMMIT (alapértelmezett) az esemény indítására szolgál, ha a tranzakció megtörtént sikeresen befejezve
  • AFTER_ROLLBACK - ha a tranzakció megtörtént visszagurult
  • AFTER_COMPLETION - ha a tranzakció megtörtént elkészült (alias a AFTER_COMMIT és AFTER_ROLLBACK)
  • BEFORE_COMMIT az esemény jobb elbocsátására szolgál előtt tranzakció elkövetni

Íme egy gyors példa a tranzakciós eseményfigyelőre:

@TransactionalEventListener (fázis = TransactionPhase.BEFORE_COMMIT) public void handleCustom (CustomSpringEvent esemény) {System.out.println ("Esemény kezelése tranzakción belül A KÖTELEZÉS ELŐTT."); }

Ezt a hallgatót csak akkor hívják meg, ha van olyan tranzakció, amelyben az esemény producere fut, és hamarosan el fogják hajtani.

És ha egyetlen tranzakció sem fut, akkor az eseményt egyáltalán nem küldjük el, kivéve, ha ezt felülírjuk a beállítással fallbackVégrehajtás tulajdonít neki igaz.

8. Következtetés

Ebben a gyors bemutatóban áttekintettük a tavaszi eseményekkel foglalkozik - egy egyszerű egyedi esemény létrehozása, közzététele, majd kezelése a hallgatóban.

Röviden áttekintettük azt is, hogyan lehet engedélyezni az események aszinkron feldolgozását a konfigurációban.

Ezután megismerkedtünk a 4.2 tavasszal bevezetett fejlesztésekkel, például az annotációval vezérelt hallgatókkal, a jobb generikus támogatással és a tranzakciós fázisokhoz kötődő eseményekkel.

Mint mindig, az ebben a cikkben bemutatott kód elérhető a Github oldalon. Ez egy Maven-alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.