Working with Events and Listeners
1. Creating Custom Application Events
Example: POJO event and legacy ApplicationEvent
// Modern: any POJO works
public record OrderPlaced(Long orderId, BigDecimal total, Instant when) {}
// Legacy: extend ApplicationEvent
public class LegacyEvent extends ApplicationEvent {
public LegacyEvent(Object source) { super(source); }
}
2. Publishing Events (ApplicationEventPublisher)
Example: Publish domain event after save
@Service
public class OrderService {
private final ApplicationEventPublisher publisher;
public OrderService(ApplicationEventPublisher publisher) { this.publisher = publisher; }
public void place(NewOrder o) {
var saved = repo.save(Order.from(o));
publisher.publishEvent(new OrderPlaced(saved.getId(), saved.getTotal(), Instant.now()));
}
}
3. Creating Event Listeners (@EventListener)
Example: Listen for domain event
@Component
public class OrderListeners {
@EventListener
public void onPlaced(OrderPlaced evt) { /* react */ }
}
| Attribute | Use |
|---|---|
classes |
Listen to multiple types |
condition |
SpEL filter |
id |
For ApplicationEventMulticaster lookup |
4. Using Conditional Event Listening
Example: Conditional event listener with SpEL
@EventListener(condition = "#evt.total > 1000")
public void highValueOrder(OrderPlaced evt) { /* premium handling */ }
5. Implementing Async Event Handling
Example: Async event handler
@Async
@EventListener
public void asyncHandler(OrderPlaced evt) { /* runs on TaskExecutor */ }
Note: Requires
@EnableAsync; publisher returns immediately.6. Ordering Event Listeners (@Order)
| Annotation | Effect |
|---|---|
@Order(1) |
Lowest = earliest |
@Order(Ordered.HIGHEST_PRECEDENCE) |
Run first |
| Default | Lowest precedence (last) |
7. Using Transaction-Bound Events (@TransactionalEventListener)
Example: Post-commit transactional event listener
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void afterCommit(OrderPlaced evt) { /* publish to MQ */ }
| Phase | Fired |
|---|---|
BEFORE_COMMIT |
Pre-commit |
AFTER_COMMIT (default) |
Post-commit success |
AFTER_ROLLBACK |
On rollback |
AFTER_COMPLETION |
Either commit or rollback |
8. Listening to Built-in Spring Events
| Event | When |
|---|---|
ContextRefreshedEvent |
Context refreshed |
ContextStartedEvent |
start() called |
ContextStoppedEvent |
stop() called |
ContextClosedEvent |
close() called |
ServletWebServerInitializedEvent |
Web server bound |
HttpSessionCreatedEvent |
Session created |
9. Creating Generic Events (ResolvableTypeProvider)
Example: Generic typed event with ResolvableType
public class TypedEvent<T> implements ResolvableTypeProvider {
private final T payload;
public TypedEvent(T payload) { this.payload = payload; }
public T payload() { return payload; }
@Override public ResolvableType getResolvableType() {
return ResolvableType.forClassWithGenerics(getClass(), ResolvableType.forInstance(payload));
}
}
@EventListener
public void onUserEvent(TypedEvent<User> e) { /* only User events */ }