Why Misusing Spring Event Can Destroy Your Service Performance
The article analyzes common pitfalls of Spring Event—such as publishing during shutdown or early startup, unsuitability for strong‑consistency use cases, and the need for graceful shutdown, idempotent listeners, and extra reliability measures—while comparing it with message‑queue solutions.
Spring Event implements a publish‑subscribe mechanism in Spring. The article shares real production‑grade pitfalls and best‑practice guidance.
1. Graceful shutdown is required before using Spring Event
During ApplicationContext shutdown, Spring forbids getBean calls; attempting to publish events then causes “Do not request a bean from a BeanFactory in a destroy method implementation” errors. In high‑traffic services, lingering requests during shutdown can trigger such failures, so traffic must be cut off (HTTP, MQ, RPC) before closing the context.
2. Events can be lost during service startup
In the author’s case, a Kafka consumer started in the bean’s init‑method published events before the @EventListener beans were registered, resulting in missed messages. The solution is to publish events only after the Spring context is fully refreshed, e.g., in SmartLifecycle or a ContextRefreshedEvent listener.
3. When to use the publish‑subscribe model
Publishers do not care how events are processed.
Publishers do not depend on processing results.
Multiple subscribers can handle events synchronously or asynchronously.
Subscribers are independent of each other.
4. Strong‑consistency scenarios are unsuitable
In order‑creation flows where inventory deduction must be atomic with order placement, Spring Event cannot propagate subscriber failures to trigger a rollback, making it inappropriate for strong‑consistency requirements.
5. Eventual‑consistency scenarios fit well
After an order is successfully placed, downstream tasks such as sending MQ messages or releasing locks can be decoupled with Spring Event because the primary transaction has already committed. Failures in these downstream tasks can be retried without affecting the original order.
6. Add reliability guarantees
Publishing with applicationContext.publishEvent(event) throws an exception if a subscriber fails. The author recommends three patterns:
Subscriber‑side retry using @Retryable (requires spring‑retry dependency).
Leverage Kafka consumer group retry semantics and dead‑letter queues.
Report unrecoverable failures to a fault‑management platform, which can trigger manual or automated retries.
@Retryable(value = Exception.class, maxAttempts = 3,
backoff = @Backoff(delay = 100L, multiplier = 2))
public void performSuccess(PerformEvent event) {
// retry logic
}7. Subscribers must be idempotent
Because a retry re‑executes all listeners, each listener’s logic must be idempotent to avoid data inconsistency.
8. Why MQ is still needed
MQ excels at inter‑service decoupling and reliable delivery across process boundaries, while Spring Event is lightweight and suited for intra‑application decoupling. They complement each other rather than replace one another.
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.
Java Architect Handbook
Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.
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.
