Why Spring Event Can Crash Your Service During Shutdown and How to Avoid It
The article recounts a production incident where Spring Event caused bean‑lookup failures during service shutdown, explains the three‑step usage of Spring Event with code examples, and presents three mitigation strategies—abandoning Spring Event, handling exceptions with MQ retries, and implementing graceful shutdown—ultimately opting to drop Spring Event.
Background
Spring Event provides a way to implement the observer pattern in Spring applications, allowing business‑logic decoupling.
Incident
During a high‑traffic period (millions of orders per day) the service logged exceptions such as “Get Bean failed” while the application context was shutting down. The stack trace showed that a bean was requested from the BeanFactory inside a destroy method, which is prohibited when the context is closing.
How Spring Event Works
Three steps are required:
Declare a custom event class that extends ApplicationEvent. A generic base class can be used to carry arbitrary payloads.
Publish the event via ApplicationContext.publishEvent(...).
Define a listener method annotated with @EventListener. Spring matches the listener based on the event type of the method parameter.
Example: Event Declaration
public class BaseEvent<T> extends ApplicationEvent {
private final T data;
public BaseEvent(T source) {
super(source);
this.data = source;
}
public T getData() {
return data;
}
}Publishing the Event
applicationContext.publishEvent(new BaseEvent<>(param));Listener Method
@EventListener
public void handleEvent(BaseEvent<PerformParam> event) {
// process event
}Root Cause
When an event is published, Spring resolves the listener bean from the application context. If the context is in the process of closing, bean lookup fails, resulting in the “Get Bean” exception. In a high‑traffic service, a request may still trigger event publication during shutdown, causing the failure.
Mitigation Options
Remove Spring Event – replace it with an explicit messaging solution (e.g., Kafka, RabbitMQ) that does not depend on the application context during shutdown.
Allow the exception, catch it at the caller, and retry the operation via a message queue.
Implement a graceful shutdown: stop accepting new RPC/HTTP/MQ traffic before the JVM exits, ensuring no events are published while the context is closing.
Decision
Given the implementation cost of the three options, the author chose to discontinue use of Spring Event and adopt a more explicit asynchronous messaging approach.
Takeaway
Framework features that appear simple can have hidden edge‑case failures. Thorough testing of shutdown behavior and conservative use of potentially risky components help maintain production stability.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
