事件机制

Spring 事件机制基于观察者模式,允许 Bean 之间通过发布 / 订阅解耦通信,避免直接方法调用带来的强依赖。

核心组件

组件说明
ApplicationEvent事件基类(Spring 4.2 后可发布任意对象)
ApplicationEventPublisher发布事件的接口,注入即用
ApplicationListener<E>监听特定事件类型的接口
@EventListener注解方式监听,更简洁(推荐)
ApplicationEventMulticaster事件多播器,负责将事件分发给监听器

基本用法

定义事件

// 方式一:继承 ApplicationEvent(携带 source)
public class OrderCreatedEvent extends ApplicationEvent {
 
    private final Order order;
 
    public OrderCreatedEvent(Object source, Order order) {
        super(source);
        this.order = order;
    }
 
    public Order getOrder() { return order; }
}
 
// 方式二:普通 POJO(Spring 4.2+,更简洁,推荐)
@Data
@AllArgsConstructor
public class OrderCreatedEvent {
    private final Order order;
    private final String operatorId;
}

发布事件

@Service
@RequiredArgsConstructor
public class OrderService {
 
    private final ApplicationEventPublisher eventPublisher;
 
    @Transactional
    public Order createOrder(CreateOrderRequest req) {
        Order order = orderRepo.save(buildOrder(req));
 
        // 事务提交前发布(默认同步,监听器在同一事务内执行)
        eventPublisher.publishEvent(new OrderCreatedEvent(order, req.getOperatorId()));
 
        return order;
    }
}

监听事件(@EventListener,推荐)

@Component
@Slf4j
public class OrderEventHandler {
 
    private final NotificationService notificationService;
    private final InventoryService inventoryService;
 
    // 基本监听
    @EventListener
    public void onOrderCreated(OrderCreatedEvent event) {
        log.info("订单创建事件: orderId={}", event.getOrder().getId());
        notificationService.sendOrderConfirmation(event.getOrder());
    }
 
    // 条件过滤(SpEL):只处理金额大于 1000 的订单
    @EventListener(condition = "#event.order.amount > 1000")
    public void onHighValueOrder(OrderCreatedEvent event) {
        notificationService.alertSalesManager(event.getOrder());
    }
 
    // 同时监听多个事件类型
    @EventListener({OrderCreatedEvent.class, OrderUpdatedEvent.class})
    public void onOrderChange(Object event) {
        inventoryService.recalculate();
    }
}

接口方式(适合泛型、复杂场景)

@Component
public class AuditLogListener implements ApplicationListener<OrderCreatedEvent> {
 
    @Override
    public void onApplicationEvent(OrderCreatedEvent event) {
        auditLogService.record(event.getOrder());
    }
}

异步事件

默认事件同步执行(监听器在发布者线程中运行)。加 @Async 让监听器在线程池中异步执行:

@Configuration
@EnableAsync   // 启用异步,一般放在启动类或配置类
public class AsyncConfig {
 
    @Bean(name = "eventExecutor")
    public Executor eventExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(8);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("event-");
        executor.initialize();
        return executor;
    }
}
 
@Component
public class EmailNotificationListener {
 
    // 在 eventExecutor 线程池中异步执行,不阻塞发布者线程
    @Async("eventExecutor")
    @EventListener
    public void sendEmail(OrderCreatedEvent event) {
        // 耗时操作:发送邮件
        emailService.send(event.getOrder().getUserEmail());
    }
}

异步监听器运行在独立线程中,不参与发布者的事务,异常也不会回滚发布者的事务。

异步与线程池详见 异步与线程池


事务事件监听(@TransactionalEventListener)

常见需求:订单创建成功提交后再发送通知,若事务回滚则不发送。

@Component
@Slf4j
public class OrderTransactionalHandler {
 
    // 默认 phase = AFTER_COMMIT:事务提交成功后才执行
    @TransactionalEventListener
    public void afterCommit(OrderCreatedEvent event) {
        // 此时订单数据已持久化,可以安全发送通知
        notificationService.sendSms(event.getOrder());
    }
 
    // 事务回滚后执行(用于补偿、告警)
    @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
    public void afterRollback(OrderCreatedEvent event) {
        log.error("订单创建事务回滚: orderId={}", event.getOrder().getId());
        alertService.notifyDeveloper(event);
    }
 
    // 无论提交还是回滚都执行
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
    public void afterCompletion(OrderCreatedEvent event) {
        // 清理临时资源
    }
 
    // 事务提交前执行(可以修改事务内的数据)
    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
    public void beforeCommit(OrderCreatedEvent event) {
        auditLogService.record(event.getOrder());
    }
}
Phase触发时机
BEFORE_COMMIT事务提交前(仍在事务内)
AFTER_COMMIT(默认)事务提交后
AFTER_ROLLBACK事务回滚后
AFTER_COMPLETION事务完成后(提交或回滚)

@TransactionalEventListener 要求发布者必须在事务中运行,否则默认不触发(可设 fallbackExecution = true 在无事务时也执行)。

事务管理详见 事务管理


有序监听(@Order)

同一事件有多个监听器时,通过 @Order 控制执行顺序(数值越小越先执行):

@EventListener
@Order(1)
public void validateOrder(OrderCreatedEvent event) {
    // 先校验
}
 
@EventListener
@Order(2)
public void deductInventory(OrderCreatedEvent event) {
    // 再扣库存
}
 
@EventListener
@Order(3)
public void sendNotification(OrderCreatedEvent event) {
    // 最后通知
}

泛型事件

// 泛型事件:EntityCreatedEvent<Order>、EntityCreatedEvent<User> 分别触发不同监听器
public class EntityCreatedEvent<T> {
    private final T entity;
    public EntityCreatedEvent(T entity) { this.entity = entity; }
    public T getEntity() { return entity; }
}
 
// 只监听 Order 的创建事件,User 的创建不会触发
@EventListener
public void onOrderCreated(EntityCreatedEvent<Order> event) {
    log.info("订单实体创建: {}", event.getEntity().getId());
}

Spring 内置生命周期事件

事件触发时机
ApplicationStartingEventSpringApplication 启动,Environment 未初始化
ApplicationEnvironmentPreparedEventEnvironment 准备好,容器未创建
ApplicationContextInitializedEventApplicationContext 创建并初始化
ApplicationPreparedEventBeanDefinition 加载完毕,未刷新
ContextRefreshedEvent容器刷新完成(所有 Bean 就绪)
ApplicationStartedEvent容器刷新完成,Runner 执行前
ApplicationReadyEventRunner 执行完毕,应用就绪接受请求
ApplicationFailedEvent启动过程中发生异常
ContextClosedEvent容器关闭
@Component
public class AppLifecycleListener {
 
    @EventListener(ApplicationReadyEvent.class)
    public void onReady() {
        log.info("应用启动完毕,开始接受请求");
        cacheService.warmup();  // 缓存预热
    }
 
    @EventListener(ContextClosedEvent.class)
    public void onClose() {
        log.info("应用即将关闭,清理资源");
    }
}

启动流程详见 启动流程


事件 vs 直接调用 vs 消息队列

对比直接方法调用Spring 事件消息队列(MQ)
耦合度强(直接依赖)弱(依赖事件类)最弱(无依赖)
可靠性同步、强一致进程内,无持久化持久化,可重试
跨服务不支持不支持支持
事务支持同一事务@TransactionalEventListener本地消息表
适用场景强依赖、同步逻辑同进程解耦、生命周期扩展跨服务、高可靠

跨服务事件驱动详见 消息队列


相关链接