Overhaul custom ApplicationEvent documentation (SPR-7422, SPR-7395)
Documentation now: - Reflects generic use of ApplicationListener interface - Demonstrates use of ApplicationEventPublisher(Aware) instead of ApplicationContext(Aware) for publishing custom events - Provides a more complete narrative as to how each of the publisher, listener, and event objects interact with one another
This commit is contained in:
parent
720f7ecf48
commit
9008cf907a
|
|
@ -7048,86 +7048,122 @@ argument.required=Ebagum lad, the '{0}' argument is required, I say, required.</
|
||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<para>You can also implement custom events. Simply call the
|
<para>You can also create and publish your own custom events. This example
|
||||||
<methodname>publishEvent()</methodname> method on the
|
demonstrates a simple class that extends Spring's
|
||||||
<interfacename>ApplicationContext</interfacename>, specifying a
|
<classname>ApplicationEvent</classname> base class:</para>
|
||||||
parameter that is an instance of your custom event class that implements
|
|
||||||
<classname>ApplicationEvent</classname>. Event listeners receive events
|
|
||||||
synchronously. This means the <methodname>publishEvent()</methodname>
|
|
||||||
method blocks until all listeners have finished processing the event.
|
|
||||||
(It is possible to supply an alternate event publishing strategy through
|
|
||||||
an <interfacename>ApplicationEventMulticaster</interfacename>
|
|
||||||
implementation). Furthermore, when a listener receives an event, it
|
|
||||||
operates inside the transaction context of the publisher, if a
|
|
||||||
transaction context is available.<!--Explain what is showing in the first and second examples?--></para>
|
|
||||||
|
|
||||||
<para>This example shows the bean definitions used to configure an
|
<programlisting language="java">public class BlackListEvent extends ApplicationEvent {
|
||||||
<interfacename>ApplicationContext</interfacename>:</para>
|
private final String address;
|
||||||
|
private final String test;
|
||||||
|
|
||||||
<programlisting language="xml"><bean id="emailer" class="example.EmailBean">
|
public BlackListEvent(Object source, String address, String test) {
|
||||||
<property name="blackList">
|
super(source);
|
||||||
<list>
|
this.address = address;
|
||||||
<value>black@list.org</value>
|
this.test = test;
|
||||||
<value>white@list.org</value>
|
}
|
||||||
<value>john@doe.org</value>
|
|
||||||
</list>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="blackListListener" class="example.BlackListNotifier">
|
<lineannotation>// accessor and other methods...</lineannotation>
|
||||||
<property name="notificationAddress" value="spam@list.org"/>
|
}</programlisting>
|
||||||
</bean></programlisting>
|
|
||||||
|
|
||||||
<para>This example shows the implementation of the classes refered to in
|
<para>To publish a custom <classname>ApplicationEvent</classname>, call
|
||||||
the previous bean definitions:</para>
|
the <methodname>publishEvent()</methodname> method on an
|
||||||
|
<interfacename>ApplicationEventPublisher</interfacename>. Typically this
|
||||||
|
is done by creating a class that implements
|
||||||
|
<interfacename>ApplicationEventPublisherAware</interfacename> and
|
||||||
|
registering it as a Spring bean. The following example demonstrates such a
|
||||||
|
class:</para>
|
||||||
|
|
||||||
<programlisting language="java">public class EmailBean implements ApplicationContextAware {
|
<programlisting language="java"><![CDATA[public class EmailService implements ApplicationEventPublisherAware {
|
||||||
|
|
||||||
private List blackList;
|
private List<String> blackList;
|
||||||
private ApplicationContext ctx;
|
private ApplicationEventPublisher publisher;
|
||||||
|
|
||||||
public void setBlackList(List blackList) {
|
public void setBlackList(List<String> blackList) {
|
||||||
this.blackList = blackList;
|
this.blackList = blackList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplicationContext(ApplicationContext ctx) {
|
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
|
||||||
this.ctx = ctx;
|
this.publisher = publisher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendEmail(String address, String text) {
|
public void sendEmail(String address, String text) {
|
||||||
if (blackList.contains(address)) {
|
if (blackList.contains(address)) {
|
||||||
BlackListEvent event = new BlackListEvent(address, text);
|
BlackListEvent event = new BlackListEvent(this, address, text);
|
||||||
ctx.publishEvent(event);
|
publisher.publishEvent(event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
<lineannotation>// send email...</lineannotation>
|
]]><lineannotation>// send email...</lineannotation><![CDATA[
|
||||||
}
|
}
|
||||||
}</programlisting>
|
}]]></programlisting>
|
||||||
|
|
||||||
<programlisting language="java">public class BlackListNotifier implements ApplicationListener {
|
<para>At configuration time, the Spring container will detect that
|
||||||
|
<classname>EmailService</classname> implements
|
||||||
|
<interfacename>ApplicationEventPublisherAware</interfacename> and will
|
||||||
|
automatically call
|
||||||
|
<methodname>setApplicationEventPublisher()</methodname>. In reality, the
|
||||||
|
parameter passed in will be the Spring container itself; you're simply
|
||||||
|
interacting with the application context via its
|
||||||
|
<interfacename>ApplicationEventPublisher</interfacename>
|
||||||
|
interface.</para>
|
||||||
|
|
||||||
|
<para>To receive the custom <classname>ApplicationEvent</classname>,
|
||||||
|
create a class that implements
|
||||||
|
<interfacename>ApplicationListener</interfacename> and register it as a
|
||||||
|
Spring bean. The following example demonstrates such a class:</para>
|
||||||
|
|
||||||
|
<programlisting language="java"><![CDATA[public class BlackListNotifier implements ApplicationListener<BlackListEvent> {
|
||||||
|
|
||||||
private String notificationAddress;
|
private String notificationAddress;
|
||||||
|
|
||||||
public void setNotificationAddress(String notificationAddress) {
|
public void setNotificationAddress(String notificationAddress) {
|
||||||
this.notificationAddress = notificationAddress;
|
this.notificationAddress = notificationAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onApplicationEvent(ApplicationEvent event) {
|
public void onApplicationEvent(BlackListEvent event) {
|
||||||
if (event instanceof BlackListEvent) {
|
]]><lineannotation> // notify appropriate parties via notificationAddress...</lineannotation><![CDATA[
|
||||||
<lineannotation>// notify appropriate person...</lineannotation>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}</programlisting>
|
}]]></programlisting>
|
||||||
|
|
||||||
<!-- MLP: Beverly to review paragraph -->
|
<para>Notice that <interfacename>ApplicationListener</interfacename> is
|
||||||
|
generically parameterized with the type of your custom event,
|
||||||
|
<classname>BlackListEvent</classname>. This means that the
|
||||||
|
<methodname>onApplicationEvent()</methodname> method can remain
|
||||||
|
type-safe, avoiding any need for downcasting. You may register as many
|
||||||
|
event listeners as you wish, but note that by default event listeners
|
||||||
|
receive events synchronously. This means the
|
||||||
|
<methodname>publishEvent()</methodname> method blocks until all
|
||||||
|
listeners have finished processing the event. One advantage of this
|
||||||
|
synchronous and single-threaded approach is that when a listener
|
||||||
|
receives an event, it operates inside the transaction context of the
|
||||||
|
publisher if a transaction context is available. If another strategy for
|
||||||
|
event publication becomes necessary, refer to the JavaDoc for Spring's
|
||||||
|
<interfacename>ApplicationEventMulticaster</interfacename>
|
||||||
|
interface.</para>
|
||||||
|
|
||||||
<para>When the sendEmail method is called, if there are any emails that
|
<para>The following example demonstrates the bean definitions used to
|
||||||
should be blacklisted, a custom event of the type BlackListEvent is
|
register and configure each of the classes above:</para>
|
||||||
published to the application context. The BlackListNotifier class which
|
<programlisting language="xml"><![CDATA[<bean id="emailService" class="example.EmailService">
|
||||||
implements the interface ApplicationListener is registered as a
|
<property name="blackList">
|
||||||
subscriber to the application context and will receive the
|
<list>
|
||||||
BlackListEvent. In order to access properties specific to
|
<value>black@list.org</value>
|
||||||
BlackListEvent, the listener must perform a downcast.</para>
|
<value>white@list.org</value>
|
||||||
|
<value>john@doe.org</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="blackListNotifier" class="example.BlackListNotifier">
|
||||||
|
<property name="notificationAddress" value="spam@list.org"/>
|
||||||
|
</bean>]]></programlisting>
|
||||||
|
|
||||||
|
<para>Putting it all together, when the <methodname>sendEmail()</methodname>
|
||||||
|
method of the <literal>emailService</literal> bean is called, if there
|
||||||
|
are any emails that should be blacklisted, a custom event of type
|
||||||
|
<classname>BlackListEvent</classname> is published. The
|
||||||
|
<literal>blackListNotifier</literal> bean is registered as an
|
||||||
|
<interfacename>ApplicationListener</interfacename> and thus receives the
|
||||||
|
<classname>BlackListEvent</classname>, at which point it can notify
|
||||||
|
appropriate parties.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="context-functionality-resources">
|
<section id="context-functionality-resources">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue