parent
e6f99ffe37
commit
0b84f137cc
|
@ -7351,7 +7351,7 @@ package also provides the following functionality:
|
|||
|
||||
* __Access to messages in i18n-style__, through the `MessageSource` interface.
|
||||
* __Access to resources__, such as URLs and files, through the `ResourceLoader` interface.
|
||||
* __Event publication__ to beans implementing the `ApplicationListener` interface,
|
||||
* __Event publication__ to namely beans implementing the `ApplicationListener` interface,
|
||||
through the use of the `ApplicationEventPublisher` interface.
|
||||
* __Loading of multiple (hierarchical) contexts__, allowing each to be focused on one
|
||||
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
|
|||
class and `ApplicationListener` interface. If a bean that implements the
|
||||
`ApplicationListener` interface is deployed into the context, every time an
|
||||
`ApplicationEvent` gets published to the `ApplicationContext`, that bean is notified.
|
||||
Essentially, this is the standard __Observer__ design pattern. Spring provides the
|
||||
following standard events:
|
||||
Essentially, this is the standard __Observer__ design pattern.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
As of Spring 4.2, the event infrastructure has been significantly improved and offer
|
||||
an <<context-functionality-events-annotation,annotation-based model>> as well as the
|
||||
ability to publish any arbitrary event, that is an object that does not necessarily
|
||||
extend from `ApplicationEvent`. When such an object is published we wrap it in a
|
||||
`PayloadApplicationEvent` for you.
|
||||
====
|
||||
|
||||
Spring provides the following standard events:
|
||||
|
||||
[[beans-ctx-events-tbl]]
|
||||
.Built-in Events
|
||||
|
@ -7747,6 +7757,97 @@ http://www.enterpriseintegrationpatterns.com[pattern-oriented], event-driven
|
|||
architectures that build upon the well-known Spring programming model.
|
||||
====
|
||||
|
||||
[[context-functionality-events-annotation]]
|
||||
==== Annotation-based Event Listeners
|
||||
|
||||
As of Spring 4.2, an event listener can be registered on any public method of a managed
|
||||
bean via the `EventListener` annotation. The `BlackListNotifier` can be rewritten as
|
||||
follows:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
public class BlackListNotifier {
|
||||
|
||||
private String notificationAddress;
|
||||
|
||||
public void setNotificationAddress(String notificationAddress) {
|
||||
this.notificationAddress = notificationAddress;
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void processBlackListEvent(BlackListEvent event) {
|
||||
// notify appropriate parties via notificationAddress...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
As you can see above, the method signature actually _infer_ which even type it listens to. This
|
||||
also works for nested generics as long as the actual event resolves the generics parameter you
|
||||
would filter on.
|
||||
|
||||
It is also possible to add additional runtime filtering via the `condition` attribute of the
|
||||
annotation that defines a <<expressions,`SpEL` expression>> that should match to actually invoke
|
||||
the method for a particular event.
|
||||
|
||||
For instance, our notifier can be rewritten to be only invoked if the `test` attribute of the
|
||||
event is equal to `foo`:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@EventListener(condition = "#event.test == 'foo'")
|
||||
public void processBlackListEvent(BlackListEvent event) {
|
||||
// notify appropriate parties via notificationAddress...
|
||||
}
|
||||
----
|
||||
|
||||
Each `SpEL` expression evaluates again a dedicated context. The next table lists the items made
|
||||
available to the context so one can use them for conditional event processing:
|
||||
|
||||
[[context-functionality-events-annotation-tbl]]
|
||||
.Event SpEL available metadata
|
||||
|===
|
||||
| Name| Location| Description| Example
|
||||
|
||||
| event
|
||||
| root object
|
||||
| The actual `ApplicationEvent`
|
||||
| `#root.event`
|
||||
|
||||
| args
|
||||
| root object
|
||||
| The arguments (as array) used for invoking the target
|
||||
| `#root.args[0]`
|
||||
|
||||
| __argument name__
|
||||
| evaluation context
|
||||
| Name of any of the method argument. If for some reason the names are not available
|
||||
(ex: no debug information), the argument names are also available under the `a<#arg>`
|
||||
where __#arg__ stands for the argument index (starting from 0).
|
||||
| `iban` or `a0` (one can also use `p0` or `p<#arg>` notation as an alias).
|
||||
|===
|
||||
|
||||
Note that `#root.event` allows you to access to the underlying event, even if your method
|
||||
signature actually refers to an arbitrary object that was published.
|
||||
|
||||
If you need to publish an event as the result of processing another, just change the
|
||||
method signature to return the event that should be published, something like:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@EventListener
|
||||
public ListUpdateEvent handleBlackListEvent(BlackListEvent event) {
|
||||
// notify appropriate parties via notificationAddress and
|
||||
// then publish a ListUpdateEvent...
|
||||
}
|
||||
----
|
||||
|
||||
This new method will publish a new `ListUpdateEvent` for every `BlackListEvent` handled
|
||||
by the method above. If you need to publish several events, just return a `Collection` of
|
||||
events instead.
|
||||
|
||||
|
||||
[[context-functionality-resources]]
|
||||
|
|
|
@ -54,6 +54,8 @@ server integration, and solutions to common problems.)
|
|||
declarative transaction management.
|
||||
* <<transaction-programmatic,Programmatic transaction management>> covers support for
|
||||
programmatic (that is, explicitly coded) transaction management.
|
||||
* <<transaction-event,Transaction bound event>> describes how you could use application
|
||||
events within a transaction.
|
||||
|
||||
|
||||
|
||||
|
@ -1924,8 +1926,44 @@ management out of business logic, and is not difficult to configure. When using
|
|||
Spring Framework, rather than EJB CMT, the configuration cost of declarative transaction
|
||||
management is greatly reduced.
|
||||
|
||||
[[transaction-event]]
|
||||
=== Transaction bound event
|
||||
|
||||
As of Spring 4.2, the listener of an event can be bound to a phase of the transaction. The
|
||||
typical example is to handle the event when the transaction has completed successfully: this
|
||||
allows events to be used with more flexibility when the outcome of the current transaction
|
||||
actually matters to the listener.
|
||||
|
||||
Registering a regular event listener is done via the `@EventListener` annotation. If you need
|
||||
to bind it to the transaction use `@TransactionalEventListener`. When you do so, the listener
|
||||
will be bound to the commit phase of the transaction by default.
|
||||
|
||||
Let's take an example to illustrate this concept. Assume that a component publish an order
|
||||
created event and we want to define a listener that should only handle that event once the
|
||||
transaction in which it has been published as committed successfully:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@Component
|
||||
public class MyComponent {
|
||||
|
||||
@TransactionalEventListener
|
||||
public void handleOrderCreatedEvent(CreationEvent<Order> creationEvent) {
|
||||
...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
The `TransactionalEventListener` annotation exposes a `phase` attribute that allows to customize
|
||||
to which phase of the transaction the listener should be bound to. The valid phases are `BEFORE_COMMIT`,
|
||||
`AFTER_COMMIT` (default), `AFTER_ROLLBACK` and `AFTER_COMPLETION` that aggregates the transaction
|
||||
completion (be it a commit or a rollback).
|
||||
|
||||
If no transaction is running, the listener is not invoked at all since we can't honor the required
|
||||
semantics. It is however possible to override that behaviour by setting the `fallbackExecution` attribute
|
||||
of the annotation to `true`.
|
||||
|
||||
[[transaction-application-server-integration]]
|
||||
=== Application server-specific integration
|
||||
|
|
Loading…
Reference in New Issue