@@ -7351,7 +7351,7 @@ package also provides the following functionality:
73517351
73527352* __Access to messages in i18n-style__, through the `MessageSource` interface.
73537353* __Access to resources__, such as URLs and files, through the `ResourceLoader` interface.
7354- * __Event publication__ to beans implementing the `ApplicationListener` interface,
7354+ * __Event publication__ to namely beans implementing the `ApplicationListener` interface,
73557355 through the use of the `ApplicationEventPublisher` interface.
73567356* __Loading of multiple (hierarchical) contexts__, allowing each to be focused on one
73577357 particular layer, such as the web layer of an application, through the
@@ -7571,8 +7571,18 @@ Event handling in the `ApplicationContext` is provided through the `ApplicationE
75717571class and `ApplicationListener` interface. If a bean that implements the
75727572`ApplicationListener` interface is deployed into the context, every time an
75737573`ApplicationEvent` gets published to the `ApplicationContext`, that bean is notified.
7574- Essentially, this is the standard __Observer__ design pattern. Spring provides the
7575- following standard events:
7574+ Essentially, this is the standard __Observer__ design pattern.
7575+
7576+ [TIP]
7577+ ====
7578+ As of Spring 4.2, the event infrastructure has been significantly improved and offer
7579+ an <<context-functionality-events-annotation,annotation-based model>> as well as the
7580+ ability to publish any arbitrary event, that is an object that does not necessarily
7581+ extend from `ApplicationEvent`. When such an object is published we wrap it in a
7582+ `PayloadApplicationEvent` for you.
7583+ ====
7584+
7585+ Spring provides the following standard events:
75767586
75777587[[beans-ctx-events-tbl]]
75787588.Built-in Events
@@ -7747,6 +7757,97 @@ http://www.enterpriseintegrationpatterns.com[pattern-oriented], event-driven
77477757architectures that build upon the well-known Spring programming model.
77487758====
77497759
7760+ [[context-functionality-events-annotation]]
7761+ ==== Annotation-based Event Listeners
7762+
7763+ As of Spring 4.2, an event listener can be registered on any public method of a managed
7764+ bean via the `EventListener` annotation. The `BlackListNotifier` can be rewritten as
7765+ follows:
7766+
7767+ [source,java,indent=0]
7768+ [subs="verbatim,quotes"]
7769+ ----
7770+ public class BlackListNotifier {
7771+
7772+ private String notificationAddress;
7773+
7774+ public void setNotificationAddress(String notificationAddress) {
7775+ this.notificationAddress = notificationAddress;
7776+ }
7777+
7778+ @EventListener
7779+ public void processBlackListEvent(BlackListEvent event) {
7780+ // notify appropriate parties via notificationAddress...
7781+ }
7782+
7783+ }
7784+ ----
7785+
7786+ As you can see above, the method signature actually _infer_ which even type it listens to. This
7787+ also works for nested generics as long as the actual event resolves the generics parameter you
7788+ would filter on.
7789+
7790+ It is also possible to add additional runtime filtering via the `condition` attribute of the
7791+ annotation that defines a <<expressions,`SpEL` expression>> that should match to actually invoke
7792+ the method for a particular event.
7793+
7794+ For instance, our notifier can be rewritten to be only invoked if the `test` attribute of the
7795+ event is equal to `foo`:
7796+
7797+ [source,java,indent=0]
7798+ [subs="verbatim,quotes"]
7799+ ----
7800+ @EventListener(condition = "#event.test == 'foo'")
7801+ public void processBlackListEvent(BlackListEvent event) {
7802+ // notify appropriate parties via notificationAddress...
7803+ }
7804+ ----
7805+
7806+ Each `SpEL` expression evaluates again a dedicated context. The next table lists the items made
7807+ available to the context so one can use them for conditional event processing:
7808+
7809+ [[context-functionality-events-annotation-tbl]]
7810+ .Event SpEL available metadata
7811+ |===
7812+ | Name| Location| Description| Example
7813+
7814+ | event
7815+ | root object
7816+ | The actual `ApplicationEvent`
7817+ | `#root.event`
7818+
7819+ | args
7820+ | root object
7821+ | The arguments (as array) used for invoking the target
7822+ | `#root.args[0]`
7823+
7824+ | __argument name__
7825+ | evaluation context
7826+ | Name of any of the method argument. If for some reason the names are not available
7827+ (ex: no debug information), the argument names are also available under the `a<#arg>`
7828+ where __#arg__ stands for the argument index (starting from 0).
7829+ | `iban` or `a0` (one can also use `p0` or `p<#arg>` notation as an alias).
7830+ |===
7831+
7832+ Note that `#root.event` allows you to access to the underlying event, even if your method
7833+ signature actually refers to an arbitrary object that was published.
7834+
7835+ If you need to publish an event as the result of processing another, just change the
7836+ method signature to return the event that should be published, something like:
7837+
7838+ [source,java,indent=0]
7839+ [subs="verbatim,quotes"]
7840+ ----
7841+ @EventListener
7842+ public ListUpdateEvent handleBlackListEvent(BlackListEvent event) {
7843+ // notify appropriate parties via notificationAddress and
7844+ // then publish a ListUpdateEvent...
7845+ }
7846+ ----
7847+
7848+ This new method will publish a new `ListUpdateEvent` for every `BlackListEvent` handled
7849+ by the method above. If you need to publish several events, just return a `Collection` of
7850+ events instead.
77507851
77517852
77527853[[context-functionality-resources]]
0 commit comments