How to Create Custom Events in Spring Boot (With Real-World Examples)

📘 Premium Read: Access my best content on Medium member-only articles — deep dives into Java, Spring Boot, Microservices, backend architecture, interview preparation, career advice, and industry-standard best practices.

✅ Some premium posts are free to read — no account needed. Follow me on Medium to stay updated and support my writing.

🎓 Top 10 Udemy Courses (Huge Discount): Explore My Udemy Courses — Learn through real-time, project-based development.

▶️ Subscribe to My YouTube Channel (172K+ subscribers): Java Guides on YouTube

Spring’s event-driven architecture allows beans to communicate without tightly coupling to each other. This makes your code cleaner, modular, and easier to maintain.

In this guide, you’ll learn how to create, publish, and listen to custom events in Spring — with real-world use cases like sending welcome emails, logging actions, or triggering workflows.


✅ What Is a Spring Event?

A Spring event is a message object that one bean publishes and another listens for. It uses the Observer pattern, allowing decoupled communication between components.

Spring already includes built-in events like ContextRefreshedEvent, but you can define your own custom events for your application logic.

🧱 Step-by-Step: Creating a Custom Event

✨ Step 1: Define the Event Class

Extend ApplicationEvent (or use a POJO in Spring 4.2+).

public class UserRegisteredEvent extends ApplicationEvent {
    private final String email;

    public UserRegisteredEvent(Object source, String email) {
        super(source);
        this.email = email;
    }

    public String getEmail() {
        return email;
    }
}

✅ From Spring 4.2 onward, you can also use any POJO — no need to extend ApplicationEvent.

🚀 Step 2: Publish the Event

Inject ApplicationEventPublisher and fire the event when needed.

@Service
public class UserService {

    private final ApplicationEventPublisher publisher;

    public UserService(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    public void registerUser(String email) {
        // Save user to DB (mocked here)
        System.out.println("User registered: " + email);
        
        // Publish custom event
        publisher.publishEvent(new UserRegisteredEvent(this, email));
    }
}

👂 Step 3: Listen to the Event

Use @EventListener on a method to handle the event.

@Component
public class WelcomeEmailListener {

    @EventListener
    public void handleUserRegistered(UserRegisteredEvent event) {
        System.out.println("Sending welcome email to: " + event.getEmail());
    }
}

🧪 Real-World Example: User Registration Flow

Let's simulate a complete flow:

  1. UserService registers the user
  2. Fires UserRegisteredEvent
  3. WelcomeEmailListener sends a welcome email
  4. AuditLogger logs the event
@Component
public class AuditLogger {

    @EventListener
    public void logEvent(UserRegisteredEvent event) {
        System.out.println("Audit: New user registered - " + event.getEmail());
    }
}

🔄 Bonus: Make Listeners Asynchronous

To make your listener non-blocking, annotate it with @Async.

@Async
@EventListener
public void sendWelcomeEmail(UserRegisteredEvent event) {
    // send email in background
}

Enable async support in your config:

@SpringBootApplication
@EnableAsync
public class Application { }

✅ This improves performance and responsiveness for non-critical tasks like sending emails or analytics tracking.

💡 When to Use Custom Events

  • 📨 Email notifications: Send welcome or reset password emails after user actions
  • 📊 Audit logging: Record changes in a separate service
  • 🧪 Testing hooks: Trigger test data setup or cleanup
  • 📦 Workflow triggers: Start downstream services or microservices after state changes

⚠️ When Not to Use Events

  • Avoid using events when you need guaranteed execution or immediate result.
  • Don’t use it for core business logic that must succeed — prefer service method calls instead.
  • Events are better for side effects, not primary outcomes.

✅ Best Practices

  • Keep event classes immutable (use final fields).
  • Use POJOs for simplicity unless you need features of ApplicationEvent.
  • Don’t assume listener execution order unless using @Order.
  • Prefer @EventListener over implementing ApplicationListener.

📌 Summary

Component Purpose
Event Class Defines the custom data being passed
Publisher Sends the event using publishEvent()
Listener Listens for and reacts to the event
Async Events Improves performance for background tasks

🔚 Final Thoughts

Spring’s event system is powerful, lightweight, and perfect for decoupling modules. By using custom events the right way, you can improve your application's architecture, modularity, and scalability.

Don't tie your classes together with direct calls — let Spring handle the communication with events.

Comments

Spring Boot 3 Paid Course Published for Free
on my Java Guides YouTube Channel

Subscribe to my YouTube Channel (165K+ subscribers):
Java Guides Channel

Top 10 My Udemy Courses with Huge Discount:
Udemy Courses - Ramesh Fadatare