Sitemap

Explaining @EventListener

3 min readJul 28, 2025

--

The EventListener annotation in Spring Framework is used to handle events in our application. Senior developers are familiar with Kafka or Event-Driven Architecture. If you have hands-on experience with Microservices, you have likely encountered event listeners. Mostly, they are used by producers and consumers, such as Apache Kafka. The example of a real-world microservice project is down below.

Press enter or click to view image in full size

An EventListener waits for incoming events and invokes the associated method when an action is detected. This mechanism also promotes loose coupling between components by decoupling the event source from the event handler.

EventListener Pros

  • Event-Driven Architecture
  • Handles Custom Built-in Events
  • Asynchronous Listeners and Orderable
  • Conditional Listening
  • Flexibility, Decoupling, and Scalability

Use Cases

1 — Custom Event Handling

Let’s understand this with an example: when a user creates an account, we should handle the email verification process, and this is exactly where the EventListener comes into play.

public class UserRegisteredEvent extends ApplicationEvent {
private final String userEmail;

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

public String getUserEmail() {
return userEmail;
}
}

Get Mehmet Basrioglu’s stories in your inbox

Join Medium for free to get updates from this writer.

@Component
public class EmailVerificationListener {

@EventListener
public void handleUserRegisteredEvent(UserRegisteredEvent event) {
String email = event.getUserEmail();
// E-posta doğrulama linki gönderme işlemi
System.out.println("Sending verification email to: " + email);
// Buraya gerçek e-posta servisi çağrısı eklenebilir.
}
}
@Service
public class UserService {

private final ApplicationEventPublisher eventPublisher;

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

public void registerUser(String email) {
// Kullanıcı kayıt işlemleri (veritabanına kaydetme vs.)
System.out.println("User registered with email: " + email);

// Event fırlatılır – işte tam bu noktada EventListener devreye girer.
eventPublisher.publishEvent(new UserRegisteredEvent(this, email));
}
}

2 — Built-In Event Handling

Automatically perform an action when the application starts, like initializing resources.

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class AppStartupListener {

@EventListener
public void onApplicationReady(ApplicationReadyEvent event) {
System.out.println("Application started — initializing resources...");

}
}

3 — Async and Non-Blocking Event Handling

When the event handling requires tasks that take significant time or resources, using Asyncallows those tasks to run asynchronously without blocking the main process.

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public Executor taskExecutor() {
return new SimpleAsyncTaskExecutor();
}
}
public class ReportGeneratedEvent extends ApplicationEvent {
private final String reportId;

public ReportGeneratedEvent(Object source, String reportId) {
super(source);
this.reportId = reportId;
}

public String getReportId() {
return reportId;
}
}
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class ReportEventListener {

@Async
@EventListener
public void handleReportGenerated(ReportGeneratedEvent event) {
System.out.println("Handling report generation for ID: " + event.getReportId());

// Simülasyon: zaman alan işlem
try {
Thread.sleep(5000); // 5 saniyelik işlem
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

System.out.println("Report processed for ID: " + event.getReportId());
}
}
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

@Service
public class ReportService {

private final ApplicationEventPublisher eventPublisher;

public ReportService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}

public void generateReport(String reportId) {
// Rapor oluşturma işlemleri...
System.out.println("Report generated with ID: " + reportId);

// Event'i yayınla — Listener asenkron şekilde çalışacak.
eventPublisher.publishEvent(new ReportGeneratedEvent(this, reportId));
}
}

4 — Conditional Event Handling

@EventListener(condition = "#event.userEmail.endsWith('@example.com')")
public void handleUserRegisteredEvent(UserRegisteredEvent event) {
// Koşul sağlanırsa çalışır
}
@EventListener(condition = "#event.status == 'ACTIVE'")                 // Durum aktifse çalışır
@EventListener(condition = "#event.score >= 75") // Skor 75 veya daha büyükse
@EventListener(condition = "#event.description?.contains('urgent')") // Description içinde 'urgent' varsa, null kontrolü ile
@EventListener(condition = "#event.userRoles?.empty == false") // Kullanıcı rolü boş değilse
@EventListener(condition = "#event.priority in {'HIGH', 'CRITICAL'}") // Priority 'HIGH' veya 'CRITICAL' ise
@EventListener(condition = "#event.loginAttempts < 3") // 3'ten az giriş denemesi varsa
@EventListener(condition = "#event.accountCreated.after(T(java.time.LocalDate).parse('2024-01-01'))") // 1 Ocak 2024 sonrası oluşturulan hesaplar
@EventListener(condition = "#event.dataMap['key'] == 'value'") // Haritadaki belirli anahtar değeri kontrolü
@EventListener(condition = "#event.message?.startsWith('Error')") // Mesaj "Error" ile başlıyorsa, null güvenli kontrol ile
@EventListener(condition = "#event.tags.?[startsWith('prod')]?.size() > 0") // Tags içinde 'prod' ile başlayan varsa
@EventListener(condition = "#event.temperature < 0 and #event.status == 'ALERT'") // Sıcaklık 0'ın altındaysa ve durum 'ALERT' ise
@EventListener(condition = "#event.isVerified == true and #event.age > 21") // Onaylanmış ve yaşı 21’den büyükse

If you found this helpful, don’t forget to follow me on Medium!

--

--

Mehmet Basrioglu
Mehmet Basrioglu

Written by Mehmet Basrioglu

Software Engineer | AWS, Java, Spring Boot, React, Kafka, Postgres, Mongo. Scalable systems. Support & Books: shopier.com/mehmetbasriogludanismanlik