ApplicationEvent
ApplicationEvent is the optional base class of events; this page also covers ApplicationEventPublisher, which sends events, and the listener types that receive them.
Why use it
You need these types when you publish events, or when an @EventListener method is not the right form of listener.
ApplicationEventPublisher: inject it into a bean that announces something. Every application context is a publisher, and the context is the bean injected for this type.ApplicationEvent: extend it when listeners need thesource(the object that raised the event) and thetimestamp. Otherwise a plain class or a record is enough.PayloadApplicationEvent<T>: the envelope the context puts around a published object that is not anApplicationEvent. Listeners ofTreceive the object itself. Listen to the envelope only when you also want its source and timestamp.ApplicationListener<E>: a bean that listens to one event type by implementing an interface. Use it when a class exists only to listen, or when code is ported from Java. An@EventListenermethod is shorter.GenericApplicationListenerandSmartApplicationListener: listeners that decide per event, or by event and source type, whether to handle it.context.addListener<E>(...): a listener for code that is not a bean, such as a Flutter widget or a test. It returns aListenerRegistration; callremove()to stop listening.
Example
import 'package:spring_core_dart/spring_core_dart.dart';
// An event with a source and a timestamp.
class OrderShipped extends ApplicationEvent {
OrderShipped(super.source, this.id);
final String id;
}
@Service()
class ShippingService {
ShippingService(this.publisher);
final ApplicationEventPublisher publisher;
// `this` is recorded as the event's source.
void ship(String id) => publisher.publishEvent(OrderShipped(this, id));
}
// A class that exists only to listen.
@Component()
@Log()
class ShipmentAudit implements ApplicationListener<OrderShipped> {
@override
void onApplicationEvent(OrderShipped event) =>
log.info('shipped ${event.id} at ${event.timestamp}');
}
Listening from code that is not a bean:
const log = SpringLog('neon.ui');
final context = ApplicationContext.run([appBeans]);
// Stays active until remove() is called, for example in a widget's dispose.
final registration = context.addListener<OrderShipped>(
(event) => log.info('shipped ${event.id}'),
);
context.getBean<ShippingService>().ship('A-17');
registration.remove();
context.close();
A listener that decides per event:
const log = SpringLog('neon.audit');
// Audits every event except the refresh.
class AuditAll implements GenericApplicationListener {
@override
bool supportsEvent(Object event) => event is! ContextRefreshedEvent;
@override
void onApplicationEvent(Object event) => log.info('audit: $event');
}
context.addApplicationListener(AuditAll());
Members
| Type | Member | Meaning |
|---|---|---|
ApplicationEvent |
ApplicationEvent(Object source, {DateTime? timestamp}) |
Creates an event raised by source; timestamp defaults to now. |
ApplicationEvent |
source |
The object that raised the event, usually the publishing bean. |
ApplicationEvent |
timestamp |
When the event was created (not when it was received). |
PayloadApplicationEvent<T> |
payload |
The published object. |
ApplicationEventPublisher |
publishEvent<T>(T event) |
Delivers event to every listener that accepts it. A non-ApplicationEvent is wrapped in a PayloadApplicationEvent<T>. |
ApplicationListener<E> |
onApplicationEvent(E event) |
Called for each event (or published object) of type E. |
GenericApplicationListener |
supportsEvent(Object event) |
Whether onApplicationEvent should get this event. |
SmartApplicationListener |
supportsEventType(Type), supportsSourceType(Type) |
Decide by the exact runtime types; a mixin with lowest precedence as default order. |
ApplicationListenerAdapter |
of<E>(handler, {order}), forListener<E>(listener, {order}) |
Turns a function or a non-bean ApplicationListener into a listener for addApplicationListener. |
ApplicationContext |
addListener<E>(listener, {order}) |
Adds a function listener; returns a ListenerRegistration. |
ListenerRegistration |
remove(), isRemoved |
Stops the listener; later calls do nothing. |
In Spring (Java)
class OrderShipped extends ApplicationEvent {
final String id;
OrderShipped(Object source, String id) { super(source); this.id = id; }
}
@Component
class ShipmentAudit implements ApplicationListener<OrderShipped> {
public void onApplicationEvent(OrderShipped event) { ... }
}
context.addApplicationListener(ApplicationListener.forPayload(
(OrderPlaced order) -> log.info("placed " + order.id())));
Differences that matter:
GenericApplicationListener.supportsEventdecides on the event instance, not on aResolvableType.addListenerreturns aListenerRegistration. Spring has no handle; you keep the listener and callremoveApplicationListener.- A listener object given to
registerSingletonthat is anApplicationListener<E>must be wrapped withApplicationListenerAdapter.forListener<E>, because Dart cannot readEfrom the object at run time.