Spring Events: Mit @EventListener und ApplicationEvents deine Applikation entkoppeln
Autor
Marcus HeldWenn du schon mit dem Spring Framework arbeitest, ist dir sicherlich aufgefallen, wie mächtig und vielseitig es ist. Eines der nützlichen - aber häufig übersehenen - Features von Spring ist das Event-Handling-System. In diesem Artikel werfen wir einen genaueren Blick darauf, wie du Events im Spring Framework mithilfe von @EventListener
konfigurieren kannst. Zusätzlich zeigen wir dir, wie diese Events in Kombination mit Transaktionen und Asynchronität verwendet werden können.
Warum Events im Spring Framework?
Events sind ein integraler Bestandteil des Spring Frameworks. Sie ermöglichen es, loosely coupled Anwendungen zu erstellen. Spring Boot nutzt Events, um den Status der Applikation zu kommunizieren. Beispiele dafür sind das ApplicationStartedEvent
. Du kannst aber auch eigene Events publizieren. Und das out-of-the-box, ohne Boilerplate und mit wenig Aufwand.
Was ist ein Event?
Ein Event in Spring, oft auch als ApplicationEvent bezeichnet, ist einfach ein Signal, dass etwas in der Anwendung passiert ist. Dieses Signal kann dann von einem oder mehreren Listenern aufgenommen werden, die darauf reagieren. Mit ApplicationEvents wird das von den ‘Gang of Four’ in ihrem bekannten Buch über Design Patterns beschriebene Observer oder Publish-Subscribe Pattern implementiert.
ApplicationEvent
Interface und ein Listener das ApplicationListener
Interface implementieren. In diesem Artikel fokussieren wir uns auf den modernen Ansatz mit der @EventListener
Annotation und POJOs.Jedes Java Objekt kann ein Event sein
Mit dem Spring Framework ist es einfach ein Event zu deklarieren. Jede Klasse kann ein Event sein. Es gibt keine Beschränkung, schreibe ein Plain Old Java Object (POJO) und halte es zur einfachen Handhabung Immutable.
class CustomSpringEvent {
private String parameter;
public CustomSpringEvent(String parameter) {
this.parameter = parameter;
}
}
Ein Event mit dem ApplicationEventPublisher veröffentlichen
Spring Boot registriert automatisch eine ApplicationEventPublisher
Bean. Diese kannst du in deinen Services injecten und zum publizieren deines Events nutzen.
@Service
public class SomeService {
private final ApplicationEventPublisher eventPublisher;
public SomeService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void someMethod() {
eventPublisher.publishEvent(new CustomSpringEvent());
}
}
Mit @EventListener ein Event empfangen
Nachdem du dein Event publiziert hast, kannst du in jeder von Spring gemanagten Bean ein Event mithilfe der @EventListener
Annotation empfangen.
@EventListener
public void handleCustomEvent(CustomSpringEvent event) {
// Irgendeine Logik
}
Events und Transaktionen
Das Handling von Events und Transaktionen kann manchmal knifflig sein. Glücklicherweise bietet Spring mit @TransactionalEventListener
eine spezielle Annotation, um dies zu erleichtern.
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(CustomSpringEvent event) {
// Irgendeine Logik
}
In diesem Beispiel wird der Event Listener erst nach dem Commit der Transaktion, die das Event ausgelöst hat, ausgeführt.
TransactionPhase.AFTER_COMMIT
ist die default phase und muss damit nicht explizit deklariert werden. Andere alternativen sind BEFORE_COMMIT
, AFTER_ROLLBACK
und AFTER_COMPLETION
.Asynchrone Events
@Async
kann mit @EventListener
kombiniert werden. Dadurch wird die Verarbeitung des Events in einem separaten Thread durchgeführt.
@EventListener
@Async
public void handleAsyncEvent(CustomSpringEvent event) {
System.out.println("Handled event asynchronously: " + event.getMessage());
}
Spring ApplicationEvents entkoppeln deine Module
Mit event-getriebenen Architekturen kannst du deine Module voneinander entkoppeln. Spring Application Events helfen dir dies umzusetzen. In einer späteren Phase der Entwicklung und wenn sich der Bedarf herausgestellt hast, ist eine Anwendung mit Application Events einfach auf Spring Integration und externe Message Queues umzustellen.