Ereignisorientierte Programmierung mit Spring und Guava’s EventBus

veröffentlicht am 01. Mai 2013

Die lose Kopplung von Komponenten ist eins der höchsten Ziele in der objektorientierten Programmierung. Eine Möglichkeit, um Komponenten voneinander zu entkoppeln, besteht in der ereignisorientierten Programmierung kombiniert mit einem EventBus. Dieser Artikel gibt eine kurze theoretische Einleitung zu dem Thema und zeigt dann eine einfache Implementierung mit dem Spring Framework und der EventBus Klasse aus dem Google Guava Projekt.

Einleitung

Die ereignisorientierte Programmierung selbst gibt keine Vorgaben, wie Events verteilt werden. So wird zum Beispiel bei der Entwicklung grafischer Oberflächen für das Drücken eines Knopfes in der Regel ein Beobachter direkt an der entsprechenden Komponente registriert.

Nutzt man einen EventBus, registrieren sich die Abonnementen (Subscriber) am EventBus und geben bekannt, für welche Ereignisse sie sich interessieren, während die Erzeuger (Publisher) einfach ihre Meldungen an den EventBus schicken. Der EventBus kümmert sich dann um die Verteilung der Nachricht an interessierte Abonnementen.

EventBus

Durch diese Methode ist eine sehr lose Kopplung der Komponenten möglich, denn die Komponenten wissen nichts voneinander und kommunizieren nur indirekt über den EventBus.

Implementierung

Das gezeigte Design kann sehr komfortabel mit dem Spring Framework und Guava’s EventBus umgesetzt werden. Für dieses Beispiel wird zunächst ein neues Maven Projekt erstellt. Neben Spring und dem Guava Framework werden auch JUnit und Mockito zum Testen der entwickelten Klassen eingebunden:

Der Quellcode konnte nicht abgerufen werden

Die Verwendung des Guava EventBus gestaltet sich sehr einfach. Soll auf ein Ereignis reagiert werden, muss einfach eine beliebige Methode des Abonnementen mit der Annotation @Subscribe versehen werden. Die Methode muss genau einen Parameter entgegennehmen, der dem gewünschten Ereignis entspricht. Damit die Subscriber nicht manuell am EventBus registriert werden müssen, wird folgender BeanPostProcessor implementiert. Dieser registriert alle von Spring verwalteten Klassen automatisch am EventBus, sofern eine mit @Subscribe annotierte Methode vorliegt:

Der Quellcode konnte nicht abgerufen werden

Damit der MessageBus auch genutzt werden kann, muss in der Spring Konfiguration eine Instanz erzeugt werden. Natürlich können auch mehrere Instanzen erzeugt werden, um beispielsweise verschiedene Abläufe voneinander zu trennen.

Der Quellcode konnte nicht abgerufen werden

In der Beispielanwendung werden neu erzeugte UUIDs über den MessageBus verteilt. Hierfür wird die UUID in einem Event Objekt verpackt, auf das interessierte Beobachter reagieren können:

Der Quellcode konnte nicht abgerufen werden

Dann wird natürlich ein Erzeuger benötigt…

Der Quellcode konnte nicht abgerufen werden

…und zuletzt wird auch der Abonnement implementiert:

Der Quellcode konnte nicht abgerufen werden

Die Anwendung wird nun über folgende Klasse gestartet:

Der Quellcode konnte nicht abgerufen werden

Komponenten testen

Natürlich soll die Lösung auch testbar sein. Deshalb folgt nun zunächst der Unit Test des Erzeugers. Es wird getestet, ob der MessageBus wirklich dazu angewiesen wird, die neue UUID zu verteilen. Der MessageBus wurde dazu durch ein Mock Objekt gestellt.

Der Quellcode konnte nicht abgerufen werden

Als nächstes wird indirekt der Abonnement getestet. Indirekt deshalb, da die einzige Methode keinen testbaren (Rückgabe)Wert hat. Der Abonnement wird hier deshalb zunächst gemockt und am EventBus registriert. Der EventBus wird dann dazu angewiesen, eine neue UUID zu verteilen. Mit dem Mock des Subscribers kann dann überprüft werden, ob die Methode zum Empfangen des Events aufgerufen wurde. Eigentlich wird hier also die korrekte Funktionsweise des MessageBus getestet :)

Der Quellcode konnte nicht abgerufen werden

Quellen und weiterführende Links

Hinterlasse einen Kommentar