Guava’s EventBus provides a publish-subscribe event mechanism which allows objects to communicate with each other via the Observer Pattern. The EventBus shies away from the traditional “Event Listener” pattern seen in Java where an object implements a particular interface and then explicitly subscribes itself with another object.
In a recent project we chose to use the EventBus in conjunction with Guice (a dependency injection library) and have had a lot of success with it. Specifically, objects in our system only have to express what events they care about without being required to explicitly register with the EventBus or any other object.
Before we go over how we bootstrapped EventBus with Guice, I think it would be a useful exercise to review the traditional and “non-guice” approaches to subscribing to events in order to illustrate the advantages of the EventBus/Guice partnership.
As stated above—the traditional method requires an interface declaration, an explicit subscription, and knowledge of the object that is posting the particular event. Additionally, it forces the object that is posting the event to invent its own method of publishing the event.
Using the EventBus eliminates the need for an interface or reference to the object that is posting the event. However, the ApplicationEventListener is still required to reference a global EventBus and register itself with it. The coupling between the global EventBus and the ApplicationEventListener eliminates the possibility of providing a flexible way of swapping out one EventBus with another without having to refactor the ApplicationEventListener.
EventBus on Guice
We are almost there! The example below utilizes Guice to inject an instance of the EventBus into the objects that require it—giving us the flexibility to swap one EventBus with another without having to refactor code. Unfortunately, it requires that we inject an EventBus instance into objects that are only going to register with it and never reference it again.
EventBus on a lot of Guice
Finally, we have arrived at our destination. Using Guice, we bind a TypeListener to every object that is created and ensure that it is registered with our default EventBus. Objects that subscribe to particular events are no longer required to explicitly subscribe with an EventBus and only need to express what kind of events they are interested in.