| 
 | ||||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES | |||||||||
See:
          Description
| Class Summary | |
|---|---|
| AsyncEventBus | An EventBusthat takes the Executor of your choice and uses it to
 dispatch events, allowing dispatch to occur asynchronously. | 
| DeadEvent | Wraps an event that was posted, but which had no subscribers and thus could not be delivered. | 
| EventBus | Dispatches events to listeners, and provides ways for listeners to register themselves. | 
| Annotation Types Summary | |
|---|---|
| AllowConcurrentEvents | Marks an event handling method as being thread-safe. | 
| Subscribe | Marks a method as an event handler, as used by AnnotatedHandlerFinderandEventBus. | 
The EventBus allows publish-subscribe-style communication between components without requiring the components to explicitly register with one another (and thus be aware of each other). It is designed exclusively to replace traditional Java in-process event distribution using explicit registration. It is not a general-purpose publish-subscribe system, nor is it intended for interprocess communication.
See the Guava User Guide article on 
 EventBus.
 
Subscribe annotation.To register your listener methods with the event producers...
registerCustomerChangeEventListener method.  These
     methods are rarely defined in common interfaces, so in addition to
     knowing every possible producer, you must also know its type.EventBus.register(Object) method on an
     EventBus.  You'll need to
     make sure that your object shares an EventBus instance with the event
     producers.To listen for a common event supertype (such as EventObject or Object)...
To listen for and detect events that were dispatched without listeners...
DeadEvent.  The
     EventBus will notify you of any events that were posted but not
     delivered.  (Handy for debugging.)To dispatch an event to listeners...
EventBus.post(Object) method.Subscribe annotation.Of course, if you'd like to have a process-wide EventBus singleton, there's nothing stopping you from doing it that way. Simply have your container (such as Guice) create the EventBus as a singleton at global scope (or stash it in a static field, if you're into that sort of thing).
In short, the EventBus is not a singleton because we'd rather not make that decision for you. Use it how you like.
In the apps using EventBus so far, this has not been a problem:
@Subscribe annotation conveys your
 intentions just as explicitly as implementing an interface (or perhaps more
 so), while leaving you free to place event handler methods wherever you wish
 and give them intention-revealing names.
 Traditional Java Events use a listener interface which typically sports only a handful of methods -- typically one. This has a number of disadvantages:
handleChangeEvent), rather than its purpose (e.g. recordChangeInJournal).
   The difficulties in implementing this cleanly has given rise to a pattern, particularly common in Swing apps, of using tiny anonymous classes to implement event listener interfaces.
Compare these two cases:
   class ChangeRecorder {
     void setCustomer(Customer cust) {
       cust.addChangeListener(new ChangeListener() {
         void customerChanged(ChangeEvent e) {
           recordChange(e.getChange());
         }
       };
     }
   }
   // Class is typically registered by the container.
   class EventBusChangeRecorder {
     @Subscribe void recordCustomerChange(ChangeEvent e) {
       recordChange(e.getChange());
     }
   }
 The intent is actually clearer in the second case: there's less noise code,
 and the event handler has a clear and meaningful name.
 Handler<T> interface?Handler<T> interface for EventBus
 listeners.  This runs into issues with Java's use of type erasure, not to
 mention problems in usability.
 Let's say the interface looked something like the following:
   interface Handler<T> {
     void handleEvent(T event);
   }
 Due to erasure, no single class can implement a generic interface more than
 once with different type parameters.  This is a giant step backwards from
 traditional Java Events, where even if actionPerformed and keyPressed aren't very meaningful names, at least you can implement both
 methods!
 register(Object) and post(Object) methods' use of the Object type.
 Object is used here for a good reason: the Event Bus library
 places no restrictions on the types of either your event listeners (as in
 register(Object)) or the events themselves (in post(Object)).
 
Event handler methods, on the other hand, must explicitly declare their argument type -- the type of event desired (or one of its supertypes). Thus, searching for references to an event class will instantly find all handler methods for that event, and renaming the type will affect all handler methods within view of your IDE (and any code that creates the event).
It's true that you can rename your @Subscribed event handler
 methods at will; Event Bus will not stop this or do anything to propagate the
 rename because, to Event Bus, the names of your handler methods are
 irrelevant.  Test code that calls the methods directly, of course, will be
 affected by your renaming -- but that's what your refactoring tools are for.
 
register a listener without any handler
 methods?The Event Bus was designed to integrate with containers and module
 systems, with Guice as the prototypical example.  In these cases, it's
 convenient to have the container/factory/environment pass every
 created object to an EventBus's register(Object) method.
 
This way, any object created by the container/factory/environment can hook into the system's event model simply by exposing handler methods.
register(Object) , the listener being
 registered is checked for the well-formedness of its handler methods.
 Specifically, any methods marked with @Subscribe must take only a
 single argument.
 Any violations of this rule will cause an IllegalArgumentException
 to be thrown.
 
(This check could be moved to compile-time using APT, a solution we're researching.)
@Subscribe annotation, or that the listening component is not loaded).
 (Note that this is not necessarily indicative of a problem. There are many cases where an application will deliberately ignore a posted event, particularly if the event is coming from code you don't control.)
To handle such events, register a handler method for the DeadEvent
 class.  Whenever EventBus receives an event with no registered handlers, it
 will turn it into a DeadEvent and pass it your way -- allowing you to
 log it or otherwise recover.
 
| 
 | ||||||||||
| PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES | |||||||||