Using Spring Application Events for Synchronous and Asynchronous Processing

This article demonstrates how to leverage Spring Application Events to decouple business logic, showing step‑by‑step examples of defining custom events, listeners, publishing events synchronously, and enabling asynchronous handling with @EnableAsync and @Async annotations, complete with code snippets and test results.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Using Spring Application Events for Synchronous and Asynchronous Processing

In this article, the author introduces Spring Application Events, demonstrating how to use them for both synchronous and asynchronous business‑logic decoupling.

Prerequisite : Complex business logic may need to be split; using events avoids the overhead of a full‑blown message queue.

Spring Event Synchronous Usage

Define a custom event class that extends ApplicationEvent:

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

/**
 * @author Strive
 * @date 2022/4/22 18:00
 */
@Data
@ToString
public class OrderProductEvent extends ApplicationEvent {
    /** 该类型事件携带的信息 */
    private String orderId;

    public OrderProductEvent(Object source, String orderId) {
        super(source);
        this.orderId = orderId;
    }
}

Define a listener that implements ApplicationListener (or use @EventListener):

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<OrderProductEvent> {
    @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));
    }
}

Publish the event from a service class using ApplicationEventPublisher (injected via ApplicationContext):

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;

    /**
     * 下单
     * @param orderId 订单ID
     */
    public String buyOrder(String orderId) {
        long start = System.currentTimeMillis();
        // 1. 查询订单详情(省略)
        // 2. 检验订单价格(同步处理)
        applicationContext.publishEvent(new OrderProductEvent(this, orderId));
        // 3. 短信通知(异步处理)
        long end = System.currentTimeMillis();
        log.info("任务全部完成,总耗时:({})毫秒", end - start);
        return "购买成功";
    }
}

A simple JUnit test verifies the flow and prints log timestamps:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class OrderServiceTest {
    @Autowired private OrderService orderService;

    @Test
    public void buyOrderTest() {
        orderService.buyOrder("732171109");
    }
}

Log output shows the synchronous listener execution time and the total task duration.

Asynchronous Usage

Enable async processing by adding @EnableAsync to the main application class:

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

Define another custom event (e.g., MsgEvent) and a listener using @EventListener with @Async:

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class MsgEvent {
    public 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 {
    @SneakyThrows
    @Async
    @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));
    }
}

Publish both events in buyOrder (the second one will be handled asynchronously):

applicationContext.publishEvent(new MsgEvent(orderId));

Running the test now shows that the asynchronous listener runs in a separate thread pool (e.g., task‑1), and the main thread finishes earlier, demonstrating the non‑blocking behavior.

Conclusion: Spring Application Events provide a lightweight, easy‑to‑use mechanism for decoupling components, suitable for both synchronous processing and, with minimal configuration, asynchronous execution, offering an alternative to heavyweight message‑queue solutions.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

springAsynchronousApplicationEvent
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

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.