Events
Events let one bean announce that something happened, and let any number of other beans react to it.
Why use it
Without events, the order service would call the mailer, the stock service and the analytics itself. Every new reaction means editing the order service. With events, the order service only publishes "order placed". The mailer, the stock and the analytics listen. Neither side knows the other.
Use events for reactions that are not part of the main job of the publisher. Do not use them when the caller needs an answer: call the other bean directly.
The context also publishes events about itself, such as ContextRefreshedEvent once every bean is ready.
Example
import 'package:spring_core_dart/spring_core_dart.dart';
// Any object can be an event; it does not need a base class.
class OrderPlaced {
const OrderPlaced(this.id, this.total);
final String id;
final double total;
}
@Service()
class Orders {
Orders(this.events);
// The context itself is injected as the publisher.
final ApplicationEventPublisher events;
void place(String id, double total) =>
events.publishEvent(OrderPlaced(id, total));
}
@Component()
@Log()
class Analytics {
// Called for every published OrderPlaced.
@EventListener()
void onPlaced(OrderPlaced order) => log.info('order ${order.id}');
}
By default listeners run inside publishEvent, so the publisher waits for them. @Async changes that for one listener.
Pages
- @EventListener: a bean method that is called for each event of its parameter type, with conditions and order.
- @Async: run a listener on a
TaskExecutor, so the publisher does not wait. - ApplicationEvent: the event base class, the publisher, and the listener interfaces.
- Context events: the events the context publishes about itself (refreshed, started, stopped, closed, ...).
In Spring (Java)
@Service
class Orders {
private final ApplicationEventPublisher events;
Orders(ApplicationEventPublisher events) { this.events = events; }
void place(String id, double total) {
events.publishEvent(new OrderPlaced(id, total));
}
}
@Component
class Analytics {
@EventListener
void onPlaced(OrderPlaced order) { ... }
}
The model is the same. The main differences: a listener condition is a Dart function instead of a SpEL string, and @Async works only on @EventListener methods.