ApplicationContext 事件发布与监听机制详解
参考文章:
ApplicationContext 事件发布与监听机制详解
Spring ApplicationEventPublisher 事件发布
需求:
利用ApplicationContext的事件机制来完成下面的功能:
1. 订单创建
2. 接受订单,分配商家
3. 商家做好了,呼叫骑手
4. 骑手收到,开始送货
5. 收到外卖
代码实现如下:
1.代码结构:

2.事件event类:
订单上下文事件
package com.publish.event;
import org.springframework.context.ApplicationEvent;
/**
* @description com.publish.event
* @author: chengyu
* @date: 2026-01-15 20:54
*
* 当父类没有默认构造方法(无参构造器)时,所有子类(无论是抽象类还是具体类)都必须在自己的构造方法中显式调用父类的某个构造方法。
*
* 原因分析
* 在Java中,子类构造方法的第一行必须调用父类的构造方法(super(...))。
* 如果父类没有默认构造方法(无参构造器),编译器不会自动生成super()调用,此时必须显式调用。
*
* 当父类有构造方法时,子类的构造方法中不需要显式调用super(),因为编译器会自动添加
* 构造方法的调用规则与类是否是抽象类无关。只要父类没有默认构造器,所有子类都必须在自己的构造方法中显式调用父类的某个构造方法
*/
public abstract class OrderContextEvent<T> extends ApplicationEvent {
public OrderContextEvent(T source) {
super(source);
}
@Override
public T getSource() {
return (T) super.getSource();
}
}
订单创建事件
package com.publish.event;
import com.publish.model.Order;
import lombok.Getter;
import lombok.Setter;
/**
* @description 订单创建事件
* @author: chengyu
* @date: 2026-01-15 20:15
*/
@Getter
@Setter
public class OrderCreatedEvent extends OrderContextEvent<Order>{
public OrderCreatedEvent(Order order) {
super(order);
}
}
呼叫骑手事件
package com.publish.event;
import com.publish.model.Order;
import com.publish.model.Rider;
import lombok.Getter;
import lombok.Setter;
/**
* @description 呼叫骑手事件
* @author: chengyu
* @date: 2026-01-15 20:21
*/
@Getter
@Setter
public class CallRiderEvent extends OrderContextEvent<Order> {
public CallRiderEvent(Order order) {
super(order);
}
}
订单送达事件
package com.publish.event;
import com.publish.model.Rider;
import lombok.Getter;
import lombok.Setter;
/**
* @description 订单送达事件
* @author: chengyu
* @date: 2026-01-15 20:24
*/
@Getter
@Setter
public class OrderArrivedEvent extends OrderContextEvent<Rider>{
public OrderArrivedEvent(Rider rider) {
super(rider);
}
}
3.实体类:
订单类
package com.publish.model;
import lombok.Data;
/**
* @description com.publish.model
* @author: chengyu
* @date: 2026-01-15 21:05
*/
@Data
public class Order {
private String orderName;
private String customerName;
private String phone;
private String address;
private String message;
}
骑手类
package com.publish.model;
import lombok.Data;
/**
* @description com.publish.model
* @author: chengyu
* @date: 2026-01-15 21:21
*/
@Data
public class Rider {
private Order order;
private String name;
private String age;
}
4.客户下单,订单创建发布事件:
package com.publish.controller;
import com.publish.event.OrderCreatedEvent;
import com.publish.model.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @description com.publish.controller
* @author: chengyu
* @date: 2026-01-15 20:30
*/
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/createOrder")
public String placeAnOrder() {
Order order = new Order();
order.setOrderName("煲仔饭");
order.setCustomerName("张三");
order.setPhone("13567678877");
order.setAddress("上海市浦东新区华胜天成小区1栋101");
order.setMessage("外卖放在家门口");
OrderCreatedEvent orderCreatedEvent = new OrderCreatedEvent(order);
applicationContext.publishEvent(orderCreatedEvent);
return "下单成功";
}
}
5.监听器:
商家接受外卖事件监听器:
package com.publish.listener;
import com.publish.event.CallRiderEvent;
import com.publish.event.OrderCreatedEvent;
import com.publish.model.Order;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @description 商家接受外卖事件监听器
* @author: chengyu
* @date: 2026-01-15 20:41
*/
@Component
@Slf4j
public class MerchantReceiveOrderListener implements ApplicationListener<OrderCreatedEvent> {
@Autowired
private ApplicationContext applicationContext;
@Override
@Async
public void onApplicationEvent(OrderCreatedEvent event) {
Order order = event.getSource();
log.info("商家收到订单:{}", order);
log.info("开始呼叫骑手..." + System.lineSeparator());
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
applicationContext.publishEvent(new CallRiderEvent(order));
}
}
骑手接受呼叫骑手事件:
package com.publish.listener;
import com.publish.event.CallRiderEvent;
import com.publish.event.OrderArrivedEvent;
import com.publish.model.Order;
import com.publish.model.Rider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @description 骑手接受呼叫骑手事件
* @author: chengyu
* @date: 2026-01-15 21:31
*/
@Component
@Slf4j
public class RiderReceiveOrderListener {
@Autowired
private ApplicationContext applicationContext;
@EventListener
@Async
public void handleCallRiderEvent(CallRiderEvent event) throws Exception {
Order order = event.getSource();
Rider rider = new Rider();
rider.setOrder(order);
rider.setAge("30");
rider.setName("饿了么潘伟");
log.info("骑手接到订单:{}", order);
log.info("骑手开始送货..." + System.lineSeparator());
TimeUnit.SECONDS.sleep(10);
applicationContext.publishEvent(new OrderArrivedEvent(rider));
}
}
客户接受外卖送达事件:
package com.publish.listener;
import com.publish.event.OrderArrivedEvent;
import com.publish.model.Rider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @description 客户接受外卖送达事件
* @author: chengyu
* @date: 2026-01-15 21:41
*/
@Component
@Slf4j
public class CustomerReceiveOrderListener {
@EventListener
@Async
public void handleOrderArrivedEvent(OrderArrivedEvent event) throws InterruptedException {
Rider rider = event.getSource();
log.info("客户收到外卖,订单信息:{}", rider.getOrder());
log.info("骑手姓名:{},骑手年龄:{},请给个好评", rider.getName(), rider.getAge());
log.info("开始好好吃饭...." + System.lineSeparator());
TimeUnit.SECONDS.sleep(10);
log.info("吃完啦!");
}
}
测试:浏览器输入:http://localhost:8080/testHello/order/createOrder
马上显示:下单成功 可见是异步。
控制台打印:
2026-01-15 22:07:37.665 INFO 4280 --- [ task-4] c.p.l.MerchantReceiveOrderListener : 商家收到订单:Order(orderName=煲仔饭, customerName=张三, phone=13567678877, address=上海市浦东新区华胜天成小区1栋101, message=外卖放在家门口)
2026-01-15 22:07:37.666 INFO 4280 --- [ task-4] c.p.l.MerchantReceiveOrderListener : 开始呼叫骑手...
2026-01-15 22:07:42.678 INFO 4280 --- [ task-5] c.p.listener.RiderReceiveOrderListener : 骑手接到订单:Order(orderName=煲仔饭, customerName=张三, phone=13567678877, address=上海市浦东新区华胜天成小区1栋101, message=外卖放在家门口)
2026-01-15 22:07:42.678 INFO 4280 --- [ task-5] c.p.listener.RiderReceiveOrderListener : 骑手开始送货...
2026-01-15 22:07:52.693 INFO 4280 --- [ task-6] c.p.l.CustomerReceiveOrderListener : 客户收到外卖,订单信息:Order(orderName=煲仔饭, customerName=张三, phone=13567678877, address=上海市浦东新区华胜天成小区1栋101, message=外卖放在家门口)
2026-01-15 22:07:52.693 INFO 4280 --- [ task-6] c.p.l.CustomerReceiveOrderListener : 骑手姓名:饿了么潘伟,骑手年龄:30,请给个好评
2026-01-15 22:07:52.693 INFO 4280 --- [ task-6] c.p.l.CustomerReceiveOrderListener : 开始好好吃饭....
2026-01-15 22:08:02.695 INFO 4280 --- [ task-6] c.p.l.CustomerReceiveOrderListener : 吃完啦!
PS:
还可以增加订单状态:OrderStatus,每一次流转定义订单的状态:创建、商家接单、骑手接单、送货、已送达
注意:
(1) ApplicationContext.publishEvent 默认是同步操作, 并非发布后不管的异步操作,发布事件后需要等 @EventListener 执行完。
(2) 如果需要开启异步操作需要在@EventListener上增加@Async 注解。
(3) 启动类上增加@EnableAsync注解
如果多个Listener监听同一个事件,比如OrderCreatedEvent,需要控制多个监听器的执行顺序,可以使用 @Order 注解:
@Component
@Order(1)
class FirstOrderListener {
@EventListener
public void handleFirst(OrderCreatedEvent event) {
System.out.println("First listener for order: " + event.getOrderId());
}
}
@Component
@Order(2)
class SecondOrderListener {
@EventListener
public void handleSecond(OrderCreatedEvent event) {
System.out.println("Second listener for order: " + event.getOrderId());
}
}
--
浙公网安备 33010602011771号