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 */ }
10. Testing Event Publishing and Handling
Example: Assert published events in test
@ SpringBootTest
@ RecordApplicationEvents
class OrderServiceTests {
@ Autowired ApplicationEvents events;
@ Autowired OrderService svc;
@ Test void publishes () {
svc. place ( new NewOrder ( /*…*/ ));
assertEquals ( 1 , events. stream (OrderPlaced.class). count ());
}
}