Backend Development 9 min read

Using Spring Application Events for Synchronous and Asynchronous Business Logic

This article explains how Spring Application Events can decouple complex business logic, demonstrates creating custom events, listeners, and publishers, shows both synchronous and asynchronous handling with @EventListener and @Async, and provides complete code examples and test results for a Spring Boot application.

Top Architect
Top Architect
Top Architect
Using Spring Application Events for Synchronous and Asynchronous Business Logic

In real-world development, business logic often becomes tangled when core and auxiliary processes are placed together, leading to long, tightly‑coupled code; tasks such as sending emails or SMS do not need to finish within the same request.

Spring Application Events (Observer pattern) offer a lightweight way to decouple these concerns without the overhead of a full‑blown message queue.

Custom Event Definition

import lombok.Data;
import lombok.ToString;
import org.springframework.context.ApplicationEvent;

@Data
@ToString
public class OrderProductEvent extends ApplicationEvent {
    /** the order id carried by the event */
    private String orderId;
    public OrderProductEvent(Object source, String orderId) {
        super(source);
        this.orderId = orderId;
    }
}

Listener Implementation (synchronous)

import com.csp.mingyue.event.events.OrderProductEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class OrderProductListener implements ApplicationListener
{
    @SneakyThrows
    @Override
    public void onApplicationEvent(OrderProductEvent event) {
        String orderId = event.getOrderId();
        long start = System.currentTimeMillis();
        Thread.sleep(2000);
        long end = System.currentTimeMillis();
        log.info("{}:校验订单商品价格耗时:({})毫秒", orderId, (end - start));
    }
}

Publisher Service

import com.csp.mingyue.event.events.OrderProductEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class OrderService {
    private final ApplicationContext applicationContext;

    public String buyOrder(String orderId) {
        long start = System.currentTimeMillis();
        // 1. query order details …
        // 2. synchronous price check via event
        applicationContext.publishEvent(new OrderProductEvent(this, orderId));
        // 3. asynchronous SMS/Email via another event (shown later)
        long end = System.currentTimeMillis();
        log.info("任务全部完成,总耗时:({})毫秒", end - start);
        return "购买成功";
    }
}

Asynchronous Handling

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class MsgEvent {
    private String orderId;
}
import com.csp.mingyue.event.events.MsgEvent;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class MsgListener {
    @Async
    @SneakyThrows
    @EventListener(MsgEvent.class)
    public void sendMsg(MsgEvent event) {
        String orderId = event.getOrderId();
        long start = System.currentTimeMillis();
        log.info("开发发送短信");
        log.info("开发发送邮件");
        Thread.sleep(4000);
        long end = System.currentTimeMillis();
        log.info("{}:发送短信、邮件耗时:({})毫秒", orderId, (end - start));
    }
}

Enable asynchronous processing in the Spring Boot entry class:

@EnableAsync
@SpringBootApplication
public class MingYueSpringbootEventApplication {
    public static void main(String[] args) {
        SpringApplication.run(MingYueSpringbootEventApplication.class, args);
    }
}

Unit tests verify both synchronous and asynchronous flows, printing logs that show the order‑price check taking ~2 seconds, the SMS/Email handling taking ~4 seconds, and the total request time around 6 seconds.

The article also includes promotional notes, QR‑code images, and links to related resources, but the core technical content remains a complete, runnable example of Spring Event usage for decoupling and async processing.

backendJavaSpringasynchronousSpring Booteventapplication-event
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.