|
13 | 13 | */
|
14 | 14 |
|
15 | 15 | /**
|
16 |
| - * The EventBus allows publish-subscribe-style communication between components without requiring |
17 |
| - * the components to explicitly register with one another (and thus be aware of each other). It is |
18 |
| - * designed exclusively to replace traditional Java in-process event distribution using explicit |
19 |
| - * registration. It is <em>not</em> a general-purpose publish-subscribe system, nor is it intended |
20 |
| - * for interprocess communication. |
| 16 | + * <a href="https://guava.dev/EventBus">Discouraged</a> in favor of dependency injection and |
| 17 | + * concurrency frameworks, EventBus allows publish-subscribe-style communication. |
21 | 18 | *
|
22 | 19 | * <p>See the Guava User Guide article on <a
|
23 | 20 | * href="https://github.com/google/guava/wiki/EventBusExplained">{@code EventBus}</a>.
|
24 |
| - * |
25 |
| - * <h2>One-Minute Guide</h2> |
26 |
| - * |
27 |
| - * <p>Converting an existing EventListener-based system to use the EventBus is easy. |
28 |
| - * |
29 |
| - * <h3>For Listeners</h3> |
30 |
| - * |
31 |
| - * <p>To listen for a specific flavor of event (say, a CustomerChangeEvent)... |
32 |
| - * |
33 |
| - * <ul> |
34 |
| - * <li><strong>...in traditional Java events:</strong> implement an interface defined with the |
35 |
| - * event — such as CustomerChangeEventListener. |
36 |
| - * <li><strong>...with EventBus:</strong> create a method that accepts CustomerChangeEvent as its |
37 |
| - * sole argument, and mark it with the {@link com.google.common.eventbus.Subscribe} |
38 |
| - * annotation. |
39 |
| - * </ul> |
40 |
| - * |
41 |
| - * <p>To register your listener methods with the event producers... |
42 |
| - * |
43 |
| - * <ul> |
44 |
| - * <li><strong>...in traditional Java events:</strong> pass your object to each producer's {@code |
45 |
| - * registerCustomerChangeEventListener} method. These methods are rarely defined in common |
46 |
| - * interfaces, so in addition to knowing every possible producer, you must also know its type. |
47 |
| - * <li><strong>...with EventBus:</strong> pass your object to the {@link |
48 |
| - * com.google.common.eventbus.EventBus#register(Object)} method on an EventBus. You'll need to |
49 |
| - * make sure that your object shares an EventBus instance with the event producers. |
50 |
| - * </ul> |
51 |
| - * |
52 |
| - * <p>To listen for a common event supertype (such as EventObject or Object)... |
53 |
| - * |
54 |
| - * <ul> |
55 |
| - * <li><strong>...in traditional Java events:</strong> not easy. |
56 |
| - * <li><strong>...with EventBus:</strong> events are automatically dispatched to listeners of any |
57 |
| - * supertype, allowing listeners for interface types or "wildcard listeners" for Object. |
58 |
| - * </ul> |
59 |
| - * |
60 |
| - * <p>To listen for and detect events that were dispatched without listeners... |
61 |
| - * |
62 |
| - * <ul> |
63 |
| - * <li><strong>...in traditional Java events:</strong> add code to each event-dispatching method |
64 |
| - * (perhaps using AOP). |
65 |
| - * <li><strong>...with EventBus:</strong> subscribe to {@link |
66 |
| - * com.google.common.eventbus.DeadEvent}. The EventBus will notify you of any events that were |
67 |
| - * posted but not delivered. (Handy for debugging.) |
68 |
| - * </ul> |
69 |
| - * |
70 |
| - * <h3>For Producers</h3> |
71 |
| - * |
72 |
| - * <p>To keep track of listeners to your events... |
73 |
| - * |
74 |
| - * <ul> |
75 |
| - * <li><strong>...in traditional Java events:</strong> write code to manage a list of listeners to |
76 |
| - * your object, including synchronization, or use a utility class like EventListenerList. |
77 |
| - * <li><strong>...with EventBus:</strong> EventBus does this for you. |
78 |
| - * </ul> |
79 |
| - * |
80 |
| - * <p>To dispatch an event to listeners... |
81 |
| - * |
82 |
| - * <ul> |
83 |
| - * <li><strong>...in traditional Java events:</strong> write a method to dispatch events to each |
84 |
| - * event listener, including error isolation and (if desired) asynchronicity. |
85 |
| - * <li><strong>...with EventBus:</strong> pass the event object to an EventBus's {@link |
86 |
| - * com.google.common.eventbus.EventBus#post(Object)} method. |
87 |
| - * </ul> |
88 |
| - * |
89 |
| - * <h2>Glossary</h2> |
90 |
| - * |
91 |
| - * <p>The EventBus system and code use the following terms to discuss event distribution: |
92 |
| - * |
93 |
| - * <dl> |
94 |
| - * <dt>Event |
95 |
| - * <dd>Any object that may be <em>posted</em> to a bus. |
96 |
| - * <dt>Subscribing |
97 |
| - * <dd>The act of registering a <em>listener</em> with an EventBus, so that its <em>subscriber |
98 |
| - * methods</em> will receive events. |
99 |
| - * <dt>Listener |
100 |
| - * <dd>An object that wishes to receive events, by exposing <em>subscriber methods</em>. |
101 |
| - * <dt>Subscriber method |
102 |
| - * <dd>A public method that the EventBus should use to deliver <em>posted</em> events. Subscriber |
103 |
| - * methods are marked by the {@link com.google.common.eventbus.Subscribe} annotation. |
104 |
| - * <dt>Posting an event |
105 |
| - * <dd>Making the event available to any <em>listeners</em> through the EventBus. |
106 |
| - * </dl> |
107 |
| - * |
108 |
| - * <h2>FAQ</h2> |
109 |
| - * |
110 |
| - * <h3>Why must I create my own Event Bus, rather than using a singleton?</h3> |
111 |
| - * |
112 |
| - * <p>The Event Bus doesn't specify how you use it; there's nothing stopping your application from |
113 |
| - * having separate EventBus instances for each component, or using separate instances to separate |
114 |
| - * events by context or topic. This also makes it trivial to set up and tear down EventBus objects |
115 |
| - * in your tests. |
116 |
| - * |
117 |
| - * <p>Of course, if you'd like to have a process-wide EventBus singleton, there's nothing stopping |
118 |
| - * you from doing it that way. Simply have your container (such as Guice) create the EventBus as a |
119 |
| - * singleton at global scope (or stash it in a static field, if you're into that sort of thing). |
120 |
| - * |
121 |
| - * <p>In short, the EventBus is not a singleton because we'd rather not make that decision for you. |
122 |
| - * Use it how you like. |
123 |
| - * |
124 |
| - * <h3>Why use an annotation to mark subscriber methods, rather than requiring the listener to |
125 |
| - * implement an interface?</h3> |
126 |
| - * |
127 |
| - * <p>We feel that the Event Bus's {@code @Subscribe} annotation conveys your intentions just as |
128 |
| - * explicitly as implementing an interface (or perhaps more so), while leaving you free to place |
129 |
| - * event subscriber methods wherever you wish and give them intention-revealing names. |
130 |
| - * |
131 |
| - * <p>Traditional Java Events use a listener interface which typically sports only a handful of |
132 |
| - * methods -- typically one. This has a number of disadvantages: |
133 |
| - * |
134 |
| - * <ul> |
135 |
| - * <li>Any one class can only implement a single response to a given event. |
136 |
| - * <li>Listener interface methods may conflict. |
137 |
| - * <li>The method must be named after the event (e.g. {@code handleChangeEvent}), rather than its |
138 |
| - * purpose (e.g. {@code recordChangeInJournal}). |
139 |
| - * <li>Each event usually has its own interface, without a common parent interface for a family of |
140 |
| - * events (e.g. all UI events). |
141 |
| - * </ul> |
142 |
| - * |
143 |
| - * <p>The difficulties in implementing this cleanly has given rise to a pattern, particularly common |
144 |
| - * in Swing apps, of using tiny anonymous classes to implement event listener interfaces. |
145 |
| - * |
146 |
| - * <p>Compare these two cases: |
147 |
| - * |
148 |
| - * <pre>{@code |
149 |
| - * class ChangeRecorder { |
150 |
| - * void setCustomer(Customer cust) { |
151 |
| - * cust.addChangeListener(new ChangeListener() { |
152 |
| - * void customerChanged(ChangeEvent e) { |
153 |
| - * recordChange(e.getChange()); |
154 |
| - * } |
155 |
| - * }; |
156 |
| - * } |
157 |
| - * } |
158 |
| - * |
159 |
| - * // Class is typically registered by the container. |
160 |
| - * class EventBusChangeRecorder { |
161 |
| - * }{@code @Subscribe void recordCustomerChange(ChangeEvent e) { |
162 |
| - * recordChange(e.getChange()); |
163 |
| - * } |
164 |
| - * } |
165 |
| - * }</pre> |
166 |
| - * |
167 |
| - * <p>The intent is actually clearer in the second case: there's less noise code, and the event |
168 |
| - * subscriber has a clear and meaningful name. |
169 |
| - * |
170 |
| - * <h3>What about a generic {@code Subscriber<T>} interface?</h3> |
171 |
| - * |
172 |
| - * <p>Some have proposed a generic {@code Subscriber<T>} interface for EventBus listeners. This runs |
173 |
| - * into issues with Java's use of type erasure, not to mention problems in usability. |
174 |
| - * |
175 |
| - * <p>Let's say the interface looked something like the following: |
176 |
| - * |
177 |
| - * <pre>{@code |
178 |
| - * interface Subscriber<T> { |
179 |
| - * void handleEvent(T event); |
180 |
| - * } |
181 |
| - * }</pre> |
182 |
| - * |
183 |
| - * <p>Due to erasure, no single class can implement a generic interface more than once with |
184 |
| - * different type parameters. This is a giant step backwards from traditional Java Events, where |
185 |
| - * even if {@code actionPerformed} and {@code keyPressed} aren't very meaningful names, at least you |
186 |
| - * can implement both methods! |
187 |
| - * |
188 |
| - * <h3>Doesn't EventBus destroy static typing and eliminate automated refactoring support?</h3> |
189 |
| - * |
190 |
| - * <p>Some have freaked out about EventBus's {@code register(Object)} and {@code post(Object)} |
191 |
| - * methods' use of the {@code Object} type. |
192 |
| - * |
193 |
| - * <p>{@code Object} is used here for a good reason: the Event Bus library places no restrictions on |
194 |
| - * the types of either your event listeners (as in {@code register(Object)}) or the events |
195 |
| - * themselves (in {@code post(Object)}). |
196 |
| - * |
197 |
| - * <p>Event subscriber methods, on the other hand, must explicitly declare their argument type -- |
198 |
| - * the type of event desired (or one of its supertypes). Thus, searching for references to an event |
199 |
| - * class will instantly find all subscriber methods for that event, and renaming the type will |
200 |
| - * affect all subscriber methods within view of your IDE (and any code that creates the event). |
201 |
| - * |
202 |
| - * <p>It's true that you can rename your {@code @Subscribed} event subscriber methods at will; Event |
203 |
| - * Bus will not stop this or do anything to propagate the rename because, to Event Bus, the names of |
204 |
| - * your subscriber methods are irrelevant. Test code that calls the methods directly, of course, |
205 |
| - * will be affected by your renaming -- but that's what your refactoring tools are for. |
206 |
| - * |
207 |
| - * <h3>What happens if I {@code register} a listener without any subscriber methods?</h3> |
208 |
| - * |
209 |
| - * <p>Nothing at all. |
210 |
| - * |
211 |
| - * <p>The Event Bus was designed to integrate with containers and module systems, with Guice as the |
212 |
| - * prototypical example. In these cases, it's convenient to have the container/factory/environment |
213 |
| - * pass <i>every</i> created object to an EventBus's {@code register(Object)} method. |
214 |
| - * |
215 |
| - * <p>This way, any object created by the container/factory/environment can hook into the system's |
216 |
| - * event model simply by exposing subscriber methods. |
217 |
| - * |
218 |
| - * <h3>What Event Bus problems can be detected at compile time?</h3> |
219 |
| - * |
220 |
| - * <p>Any problem that can be unambiguously detected by Java's type system. For example, defining a |
221 |
| - * subscriber method for a nonexistent event type. |
222 |
| - * |
223 |
| - * <h3>What Event Bus problems can be detected immediately at registration?</h3> |
224 |
| - * |
225 |
| - * <p>Immediately upon invoking {@code register(Object)}, the listener being registered is checked |
226 |
| - * for the <i>well-formedness</i> of its subscriber methods. Specifically, any methods marked with |
227 |
| - * {@code @Subscribe} must take only a single argument. |
228 |
| - * |
229 |
| - * <p>Any violations of this rule will cause an {@code IllegalArgumentException} to be thrown. |
230 |
| - * |
231 |
| - * <p>(This check could be moved to compile-time using APT, a solution we're researching.) |
232 |
| - * |
233 |
| - * <h3>What Event Bus problems may only be detected later, at runtime?</h3> |
234 |
| - * |
235 |
| - * <p>If a component posts events with no registered listeners, it <i>may</i> indicate an error |
236 |
| - * (typically an indication that you missed a {@code @Subscribe} annotation, or that the listening |
237 |
| - * component is not loaded). |
238 |
| - * |
239 |
| - * <p>(Note that this is <i>not necessarily</i> indicative of a problem. There are many cases where |
240 |
| - * an application will deliberately ignore a posted event, particularly if the event is coming from |
241 |
| - * code you don't control.) |
242 |
| - * |
243 |
| - * <p>To handle such events, register a subscriber method for the {@code DeadEvent} class. Whenever |
244 |
| - * EventBus receives an event with no registered subscribers, it will turn it into a {@code |
245 |
| - * DeadEvent} and pass it your way -- allowing you to log it or otherwise recover. |
246 |
| - * |
247 |
| - * <h3>How do I test event listeners and their subscriber methods?</h3> |
248 |
| - * |
249 |
| - * <p>Because subscriber methods on your listener classes are normal methods, you can simply call |
250 |
| - * them from your test code to simulate the EventBus. |
251 | 21 | */
|
252 | 22 | @CheckReturnValue
|
253 | 23 | @ParametersAreNonnullByDefault
|
|
0 commit comments