18-Spring-Framework-事件机制详解

2 阅读10分钟

Spring 事件机制详解

一、知识概述

Spring 事件机制是基于观察者模式实现的事件驱动模型,允许应用组件之间通过发布和监听事件进行松耦合通信。这种机制使得组件之间无需直接依赖,提高了代码的可维护性和可扩展性。

Spring 事件机制核心组件:

  • ApplicationEvent:事件基类
  • ApplicationListener:事件监听器接口
  • ApplicationEventPublisher:事件发布接口
  • ApplicationEventMulticaster:事件广播器

理解 Spring 事件机制,有助于实现业务解耦和异步处理。

二、知识点详细讲解

2.1 观察者模式

模式结构
Subject(被观察者)
    ↓ 通知
Observer(观察者)

Spring 事件机制:

ApplicationEventPublisher(发布者)
    ↓ 发布事件
ApplicationEventMulticaster(广播器)
    ↓ 广播事件
ApplicationListener(监听器)

2.2 核心接口

ApplicationEvent
public abstract class ApplicationEvent extends EventObject {
    private final long timestamp;
    
    public ApplicationEvent(Object source) {
        super(source);
        this.timestamp = System.currentTimeMillis();
    }
    
    public long getTimestamp() {
        return timestamp;
    }
}
ApplicationListener
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> {
    void onApplicationEvent(E event);
}
ApplicationEventPublisher
@FunctionalInterface
public interface ApplicationEventPublisher {
    default void publishEvent(ApplicationEvent event) {
        publishEvent((Object) event);
    }
    
    void publishEvent(Object event);
}

2.3 内置事件

事件触发时机
ContextRefreshedEvent容器刷新完成
ContextStartedEvent容器启动
ContextStoppedEvent容器停止
ContextClosedEvent容器关闭
RequestHandledEvent请求处理完成

2.4 事件监听方式

  1. 实现 ApplicationListener 接口
  2. @EventListener 注解
  3. @TransactionalEventListener 注解

2.5 异步事件

默认情况下,Spring 事件是同步执行的。要实现异步事件:

  1. @Async + @EventListener
  2. 自定义 ApplicationEventMulticaster

2.6 事件传播

  • Spring 事件默认在当前上下文传播
  • 父子上下文之间事件会传播
  • 可通过实现 ApplicationEventPublisherAware 获取发布者

三、代码示例

3.1 自定义事件基础

import org.springframework.context.*;
import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.time.LocalDateTime;
import java.util.*;

// 自定义事件基类
public abstract class BaseEvent extends ApplicationEvent {
    private final LocalDateTime eventTime;
    private final String eventId;
    
    public BaseEvent(Object source) {
        super(source);
        this.eventTime = LocalDateTime.now();
        this.eventId = UUID.randomUUID().toString();
    }
    
    public LocalDateTime getEventTime() {
        return eventTime;
    }
    
    public String getEventId() {
        return eventId;
    }
}

// 用户创建事件
public class UserCreatedEvent extends BaseEvent {
    private final Long userId;
    private final String username;
    private final String email;
    
    public UserCreatedEvent(Object source, Long userId, String username, String email) {
        super(source);
        this.userId = userId;
        this.username = username;
        this.email = email;
    }
    
    public Long getUserId() { return userId; }
    public String getUsername() { return username; }
    public String getEmail() { return email; }
    
    @Override
    public String toString() {
        return String.format("UserCreatedEvent{userId=%d, username='%s'}", userId, username);
    }
}

// 用户更新事件
public class UserUpdatedEvent extends BaseEvent {
    private final Long userId;
    private final String oldUsername;
    private final String newUsername;
    
    public UserUpdatedEvent(Object source, Long userId, String oldUsername, String newUsername) {
        super(source);
        this.userId = userId;
        this.oldUsername = oldUsername;
        this.newUsername = newUsername;
    }
    
    public Long getUserId() { return userId; }
    public String getOldUsername() { return oldUsername; }
    public String getNewUsername() { return newUsername; }
}

// 用户删除事件
public class UserDeletedEvent extends BaseEvent {
    private final Long userId;
    
    public UserDeletedEvent(Object source, Long userId) {
        super(source);
        this.userId = userId;
    }
    
    public Long getUserId() { return userId; }
}

// 事件发布者
@Service
public class UserService {
    
    private final ApplicationEventPublisher eventPublisher;
    private final Map<Long, User> users = new ConcurrentHashMap<>();
    private final AtomicLong idGenerator = new AtomicLong(1);
    
    public UserService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    
    public User createUser(String username, String email) {
        Long userId = idGenerator.getAndIncrement();
        User user = new User(userId, username, email);
        users.put(userId, user);
        
        // 发布用户创建事件
        UserCreatedEvent event = new UserCreatedEvent(this, userId, username, email);
        eventPublisher.publishEvent(event);
        
        System.out.println("用户创建完成: " + user);
        return user;
    }
    
    public User updateUser(Long userId, String newUsername) {
        User user = users.get(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        String oldUsername = user.getUsername();
        user.setUsername(newUsername);
        
        // 发布用户更新事件
        UserUpdatedEvent event = new UserUpdatedEvent(this, userId, oldUsername, newUsername);
        eventPublisher.publishEvent(event);
        
        return user;
    }
    
    public void deleteUser(Long userId) {
        users.remove(userId);
        
        // 发布用户删除事件
        UserDeletedEvent event = new UserDeletedEvent(this, userId);
        eventPublisher.publishEvent(event);
    }
}

// 用户实体
public class User {
    private Long id;
    private String username;
    private String email;
    
    public User(Long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
    }
    
    // getter/setter
    public Long getId() { return id; }
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    public String getEmail() { return email; }
    
    @Override
    public String toString() {
        return "User{id=" + id + ", username='" + username + "'}";
    }
}

3.2 事件监听器实现方式

import org.springframework.context.*;
import org.springframework.context.event.*;
import org.springframework.stereotype.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.event.*;

// 方式1:实现 ApplicationListener 接口
@Component
public class UserCreatedListener implements ApplicationListener<UserCreatedEvent> {
    
    @Override
    public void onApplicationEvent(UserCreatedEvent event) {
        System.out.println("[接口方式] 收到用户创建事件: " + event);
        // 处理逻辑
    }
}

// 方式2:使用 @EventListener 注解(推荐)
@Component
public class UserEventListener {
    
    @EventListener
    public void onUserCreated(UserCreatedEvent event) {
        System.out.println("[@EventListener] 用户创建: " + event.getUsername());
        // 发送欢迎邮件
        sendWelcomeEmail(event.getEmail());
    }
    
    @EventListener
    public void onUserUpdated(UserUpdatedEvent event) {
        System.out.println("[@EventListener] 用户更新: " + 
            event.getOldUsername() + " -> " + event.getNewUsername());
    }
    
    @EventListener
    public void onUserDeleted(UserDeletedEvent event) {
        System.out.println("[@EventListener] 用户删除: " + event.getUserId());
        // 清理相关数据
    }
    
    // 监听多种事件类型
    @EventListener({UserCreatedEvent.class, UserUpdatedEvent.class})
    public void onUserChanged(ApplicationEvent event) {
        System.out.println("[@EventListener] 用户信息变更");
        // 记录变更日志
    }
    
    // 条件监听
    @EventListener(condition = "#event.username.contains('admin')")
    public void onAdminUserCreated(UserCreatedEvent event) {
        System.out.println("[@EventListener] 管理员用户创建: " + event.getUsername());
    }
    
    private void sendWelcomeEmail(String email) {
        System.out.println("发送欢迎邮件到: " + email);
    }
}

3.3 异步事件处理

import org.springframework.context.event.*;
import org.springframework.scheduling.annotation.*;
import org.springframework.stereotype.*;
import org.springframework.transaction.annotation.*;
import java.util.concurrent.*;

@Configuration
@EnableAsync
public class AsyncEventConfig {
    
    @Bean(name = "eventExecutor")
    public Executor eventExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("event-async-");
        executor.initialize();
        return executor;
    }
}

@Component
public class AsyncUserEventListener {
    
    // 异步处理事件
    @Async("eventExecutor")
    @EventListener
    public void handleUserCreatedAsync(UserCreatedEvent event) {
        System.out.println("[异步处理] 开始处理用户创建事件: " + event);
        System.out.println("当前线程: " + Thread.currentThread().getName());
        
        // 模拟耗时操作
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println("[异步处理] 用户创建事件处理完成");
    }
    
    // 指定异常处理
    @Async("eventExecutor")
    @EventListener
    public void handleEventWithError(UserCreatedEvent event) {
        try {
            // 处理逻辑
            System.out.println("处理用户创建事件");
        } catch (Exception e) {
            System.err.println("事件处理异常: " + e.getMessage());
        }
    }
}

// 自定义异步事件广播器
@Configuration
public class AsyncEventMulticasterConfig {
    
    @Bean(name = "applicationEventMulticaster")
    public ApplicationEventMulticaster simpleApplicationEventMulticaster() {
        SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
        
        // 设置异步执行器
        multicaster.setTaskExecutor(new SimpleAsyncTaskExecutor("event-"));
        
        return multicaster;
    }
}

3.4 事务事件监听

import org.springframework.transaction.event.*;
import org.springframework.stereotype.*;
import org.springframework.transaction.annotation.*;

@Component
public class TransactionalUserEventListener {
    
    // 事务提交后执行
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void afterCommit(UserCreatedEvent event) {
        System.out.println("[事务提交后] 处理用户创建事件: " + event);
        // 此时事务已提交,可以安全执行外部操作
        sendNotification(event);
    }
    
    // 事务回滚后执行
    @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
    public void afterRollback(UserCreatedEvent event) {
        System.out.println("[事务回滚后] 用户创建失败: " + event);
        // 记录失败日志
    }
    
    // 事务完成后执行(无论提交或回滚)
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
    public void afterCompletion(UserCreatedEvent event) {
        System.out.println("[事务完成后] 清理资源");
    }
    
    // 事务提交前执行
    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
    public void beforeCommit(UserCreatedEvent event) {
        System.out.println("[事务提交前] 最后检查");
    }
    
    private void sendNotification(UserCreatedEvent event) {
        System.out.println("发送用户创建通知: " + event.getEmail());
    }
}

// 服务层使用事务
@Service
public class UserTransactionService {
    
    private final ApplicationEventPublisher eventPublisher;
    private final UserDao userDao;
    
    public UserTransactionService(ApplicationEventPublisher eventPublisher, 
                                  UserDao userDao) {
        this.eventPublisher = eventPublisher;
        this.userDao = userDao;
    }
    
    @Transactional
    public User createUserWithTransaction(String username, String email) {
        User user = new User(null, username, email);
        userDao.save(user);
        
        // 发布事件
        // 只有事务提交后,@TransactionalEventListener 才会执行
        UserCreatedEvent event = new UserCreatedEvent(this, user.getId(), username, email);
        eventPublisher.publishEvent(event);
        
        return user;
    }
    
    @Transactional
    public void createUserWithFailure(String username) {
        User user = new User(null, username, "test@example.com");
        userDao.save(user);
        
        eventPublisher.publishEvent(new UserCreatedEvent(this, user.getId(), username, "test@example.com"));
        
        // 模拟异常导致事务回滚
        throw new RuntimeException("模拟异常");
    }
}

3.5 内置事件监听

import org.springframework.context.*;
import org.springframework.context.event.*;
import org.springframework.stereotype.*;
import org.springframework.web.context.support.*;

@Component
public class SpringBuiltInEventListener {
    
    // 容器刷新完成
    @EventListener
    public void onContextRefreshed(ContextRefreshedEvent event) {
        System.out.println("=== 容器刷新完成 ===");
        System.out.println("ApplicationContext: " + event.getApplicationContext());
        System.out.println("Bean 数量: " + event.getApplicationContext().getBeanDefinitionCount());
    }
    
    // 容器启动
    @EventListener
    public void onContextStarted(ContextStartedEvent event) {
        System.out.println("=== 容器启动 ===");
    }
    
    // 容器停止
    @EventListener
    public void onContextStopped(ContextStoppedEvent event) {
        System.out.println("=== 容器停止 ===");
    }
    
    // 容器关闭
    @EventListener
    public void onContextClosed(ContextClosedEvent event) {
        System.out.println("=== 容器关闭 ===");
        // 清理资源
    }
    
    // Web 请求处理完成
    @EventListener
    public void onRequestHandled(RequestHandledEvent event) {
        System.out.println("=== 请求处理完成 ===");
        System.out.println("请求路径: " + event.getDescription());
    }
}

// 使用 ApplicationListener 接口
@Component
public class ApplicationStartupListener implements ApplicationListener<ContextRefreshedEvent> {
    
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 容器启动完成后的初始化逻辑
        System.out.println("容器启动完成,执行初始化操作...");
        
        // 例如:加载缓存、建立连接等
    }
}

3.6 事件继承与泛型

import org.springframework.context.*;
import org.springframework.context.event.*;
import org.springframework.stereotype.*;
import java.util.*;

// 泛型事件
public class GenericEvent<T> extends ApplicationEvent {
    private final T data;
    
    public GenericEvent(Object source, T data) {
        super(source);
        this.data = data;
    }
    
    public T getData() {
        return data;
    }
}

// 特定类型事件
public class OrderEvent extends GenericEvent<Order> {
    private final OrderEventType eventType;
    
    public OrderEvent(Object source, Order order, OrderEventType eventType) {
        super(source, order);
        this.eventType = eventType;
    }
    
    public OrderEventType getEventType() {
        return eventType;
    }
    
    public Order getOrder() {
        return getData();
    }
}

public enum OrderEventType {
    CREATED, PAID, SHIPPED, DELIVERED, CANCELLED
}

// 订单实体
public class Order {
    private Long id;
    private Long userId;
    private BigDecimal amount;
    private OrderStatus status;
    
    // getter/setter
}

// 监听泛型事件
@Component
public class GenericEventListener {
    
    // 监听所有 GenericEvent
    @EventListener
    public void onGenericEvent(GenericEvent<?> event) {
        System.out.println("收到泛型事件: " + event.getData());
    }
    
    // 监听特定类型的泛型事件
    @EventListener
    public void onOrderEvent(GenericEvent<Order> event) {
        System.out.println("收到订单事件: " + event.getData());
    }
    
    // 监听子类事件
    @EventListener
    public void onOrderCreatedEvent(OrderEvent event) {
        System.out.println("订单事件: " + event.getEventType() + ", " + event.getOrder());
    }
}

// 使用继承的事件
public class BaseEntityEvent extends ApplicationEvent {
    private final Long entityId;
    private final Class<?> entityClass;
    
    public BaseEntityEvent(Object source, Long entityId, Class<?> entityClass) {
        super(source);
        this.entityId = entityId;
        this.entityClass = entityClass;
    }
    
    public Long getEntityId() { return entityId; }
    public Class<?> getEntityClass() { return entityClass; }
}

public class ProductCreatedEvent extends BaseEntityEvent {
    public ProductCreatedEvent(Object source, Long productId) {
        super(source, productId, Product.class);
    }
}

@Component
public class EntityEventListener {
    
    // 监听所有实体事件
    @EventListener
    public void onEntityEvent(BaseEntityEvent event) {
        System.out.println("实体事件: " + event.getEntityClass().getSimpleName() + 
            ", ID: " + event.getEntityId());
    }
    
    // 只监听产品事件
    @EventListener
    public void onProductEvent(ProductCreatedEvent event) {
        System.out.println("产品创建事件: " + event.getEntityId());
    }
}

3.7 事件发布工具类

import org.springframework.context.*;
import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.function.Consumer;

@Component
public class EventPublisher {
    
    private final ApplicationEventPublisher publisher;
    
    public EventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }
    
    // 同步发布
    public void publish(ApplicationEvent event) {
        publisher.publishEvent(event);
    }
    
    // 发布任意对象作为事件
    public void publish(Object event) {
        publisher.publishEvent(event);
    }
    
    // 链式发布
    public EventPublisher publishEvent(ApplicationEvent event) {
        publisher.publishEvent(event);
        return this;
    }
    
    // 带回调的发布
    public void publishWithCallback(ApplicationEvent event, Runnable callback) {
        try {
            publisher.publishEvent(event);
            callback.run();
        } catch (Exception e) {
            System.err.println("事件发布失败: " + e.getMessage());
        }
    }
}

// 事件构建器
public class EventBuilder {
    
    public static UserCreatedEvent userCreated(Long userId, String username, String email) {
        return new UserCreatedEvent(EventBuilder.class, userId, username, email);
    }
    
    public static UserUpdatedEvent userUpdated(Long userId, String oldName, String newName) {
        return new UserUpdatedEvent(EventBuilder.class, userId, oldName, newName);
    }
    
    public static UserDeletedEvent userDeleted(Long userId) {
        return new UserDeletedEvent(EventBuilder.class, userId);
    }
}

// 使用示例
@Service
public class UserEventService {
    
    private final EventPublisher eventPublisher;
    
    public UserEventService(EventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    
    public void demo() {
        // 使用构建器发布事件
        eventPublisher.publish(EventBuilder.userCreated(1L, "张三", "zhangsan@example.com"));
        
        // 链式发布
        eventPublisher
            .publishEvent(EventBuilder.userCreated(1L, "张三", "zhangsan@example.com"))
            .publishEvent(EventBuilder.userUpdated(1L, "张三", "李四"));
    }
}

四、实战应用场景

4.1 用户注册流程

import org.springframework.context.*;
import org.springframework.context.event.*;
import org.springframework.stereotype.*;
import org.springframework.scheduling.annotation.*;
import org.springframework.transaction.event.*;
import java.util.*;

// 用户注册事件
public class UserRegisteredEvent extends ApplicationEvent {
    private final User user;
    private final String registerIp;
    
    public UserRegisteredEvent(Object source, User user, String registerIp) {
        super(source);
        this.user = user;
        this.registerIp = registerIp;
    }
    
    public User getUser() { return user; }
    public String getRegisterIp() { return registerIp; }
}

// 用户注册服务
@Service
public class UserRegistrationService {
    
    private final UserDao userDao;
    private final ApplicationEventPublisher eventPublisher;
    
    public UserRegistrationService(UserDao userDao, 
                                   ApplicationEventPublisher eventPublisher) {
        this.userDao = userDao;
        this.eventPublisher = eventPublisher;
    }
    
    @Transactional
    public User register(String username, String email, String password, String registerIp) {
        // 1. 创建用户
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        user.setPassword(encodePassword(password));
        user.setStatus(UserStatus.PENDING);
        
        userDao.save(user);
        
        // 2. 发布注册事件(事务提交后执行监听器)
        eventPublisher.publishEvent(new UserRegisteredEvent(this, user, registerIp));
        
        return user;
    }
    
    private String encodePassword(String password) {
        return password;  // 简化
    }
}

// 邮件服务监听器
@Component
public class EmailNotificationListener {
    
    @Async
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void onUserRegistered(UserRegisteredEvent event) {
        User user = event.getUser();
        
        // 发送欢迎邮件
        sendWelcomeEmail(user.getEmail(), user.getUsername());
        
        // 发送验证邮件
        sendVerificationEmail(user.getEmail(), user.getId());
    }
    
    private void sendWelcomeEmail(String email, String username) {
        System.out.println("发送欢迎邮件到: " + email);
    }
    
    private void sendVerificationEmail(String email, Long userId) {
        System.out.println("发送验证邮件到: " + email);
    }
}

// 积分服务监听器
@Component
public class PointsListener {
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void onUserRegistered(UserRegisteredEvent event) {
        // 赠送新用户积分
        System.out.println("为新用户赠送积分: " + event.getUser().getId());
    }
}

// 日志监听器
@Component
public class AuditLogListener {
    
    @EventListener
    public void onUserRegistered(UserRegisteredEvent event) {
        // 记录注册日志
        System.out.println("用户注册日志: userId=" + event.getUser().getId() + 
            ", ip=" + event.getRegisterIp());
    }
}

// 风控监听器
@Component
public class RiskControlListener {
    
    @EventListener
    public void onUserRegistered(UserRegisteredEvent event) {
        String ip = event.getRegisterIp();
        
        // 检查 IP 风险
        if (isHighRiskIp(ip)) {
            System.out.println("高风险 IP 注册: " + ip);
        }
    }
    
    private boolean isHighRiskIp(String ip) {
        return false;  // 简化
    }
}

4.2 订单状态变更

import org.springframework.context.*;
import org.springframework.context.event.*;
import org.springframework.stereotype.*;
import org.springframework.transaction.event.*;
import java.util.*;

// 订单状态变更事件
public class OrderStatusChangedEvent extends ApplicationEvent {
    private final Long orderId;
    private final OrderStatus oldStatus;
    private final OrderStatus newStatus;
    private final Long userId;
    
    public OrderStatusChangedEvent(Object source, Long orderId, 
                                   OrderStatus oldStatus, OrderStatus newStatus, 
                                   Long userId) {
        super(source);
        this.orderId = orderId;
        this.oldStatus = oldStatus;
        this.newStatus = newStatus;
        this.userId = userId;
    }
    
    // getter
    public Long getOrderId() { return orderId; }
    public OrderStatus getOldStatus() { return oldStatus; }
    public OrderStatus getNewStatus() { return newStatus; }
    public Long getUserId() { return userId; }
}

// 订单状态枚举
public enum OrderStatus {
    PENDING, PAID, SHIPPED, DELIVERED, CANCELLED
}

// 订单服务
@Service
public class OrderService {
    
    private final OrderDao orderDao;
    private final ApplicationEventPublisher eventPublisher;
    
    public OrderService(OrderDao orderDao, ApplicationEventPublisher eventPublisher) {
        this.orderDao = orderDao;
        this.eventPublisher = eventPublisher;
    }
    
    @Transactional
    public void payOrder(Long orderId, Long userId) {
        Order order = orderDao.findById(orderId);
        
        if (order.getStatus() != OrderStatus.PENDING) {
            throw new BusinessException("订单状态不正确");
        }
        
        OrderStatus oldStatus = order.getStatus();
        order.setStatus(OrderStatus.PAID);
        orderDao.update(order);
        
        // 发布状态变更事件
        eventPublisher.publishEvent(new OrderStatusChangedEvent(
            this, orderId, oldStatus, OrderStatus.PAID, userId));
    }
    
    @Transactional
    public void shipOrder(Long orderId, String trackingNo) {
        Order order = orderDao.findById(orderId);
        
        if (order.getStatus() != OrderStatus.PAID) {
            throw new BusinessException("订单未支付");
        }
        
        OrderStatus oldStatus = order.getStatus();
        order.setStatus(OrderStatus.SHIPPED);
        order.setTrackingNo(trackingNo);
        orderDao.update(order);
        
        eventPublisher.publishEvent(new OrderStatusChangedEvent(
            this, orderId, oldStatus, OrderStatus.SHIPPED, order.getUserId()));
    }
}

// 通知监听器
@Component
public class OrderNotificationListener {
    
    @Async
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void onOrderPaid(OrderStatusChangedEvent event) {
        if (event.getNewStatus() == OrderStatus.PAID) {
            // 发送支付成功通知
            sendPaymentNotification(event.getUserId(), event.getOrderId());
        }
    }
    
    @Async
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void onOrderShipped(OrderStatusChangedEvent event) {
        if (event.getNewStatus() == OrderStatus.SHIPPED) {
            // 发送发货通知
            sendShippingNotification(event.getUserId(), event.getOrderId());
        }
    }
    
    private void sendPaymentNotification(Long userId, Long orderId) {
        System.out.println("发送支付成功通知: userId=" + userId + ", orderId=" + orderId);
    }
    
    private void sendShippingNotification(Long userId, Long orderId) {
        System.out.println("发送发货通知: userId=" + userId + ", orderId=" + orderId);
    }
}

// 积分监听器
@Component
public class OrderPointsListener {
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void onOrderPaid(OrderStatusChangedEvent event) {
        if (event.getNewStatus() == OrderStatus.PAID) {
            // 计算并赠送积分
            System.out.println("订单支付完成,赠送积分: orderId=" + event.getOrderId());
        }
    }
}

4.3 缓存更新

import org.springframework.context.*;
import org.springframework.context.event.*;
import org.springframework.stereotype.*;
import java.util.concurrent.*;

// 缓存失效事件
public class CacheInvalidationEvent extends ApplicationEvent {
    private final String cacheName;
    private final Object key;
    
    public CacheInvalidationEvent(Object source, String cacheName, Object key) {
        super(source);
        this.cacheName = cacheName;
        this.key = key;
    }
    
    public String getCacheName() { return cacheName; }
    public Object getKey() { return key; }
}

// 缓存服务
@Service
public class CacheService {
    
    private final Map<String, Map<Object, Object>> caches = new ConcurrentHashMap<>();
    private final ApplicationEventPublisher eventPublisher;
    
    public CacheService(ApplicationEventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }
    
    public Object get(String cacheName, Object key) {
        Map<Object, Object> cache = caches.get(cacheName);
        return cache != null ? cache.get(key) : null;
    }
    
    public void put(String cacheName, Object key, Object value) {
        caches.computeIfAbsent(cacheName, k -> new ConcurrentHashMap<>())
            .put(key, value);
    }
    
    public void evict(String cacheName, Object key) {
        Map<Object, Object> cache = caches.get(cacheName);
        if (cache != null) {
            cache.remove(key);
        }
        
        // 发布缓存失效事件
        eventPublisher.publishEvent(new CacheInvalidationEvent(this, cacheName, key));
    }
    
    public void clear(String cacheName) {
        caches.remove(cacheName);
        
        // 发布全量失效事件
        eventPublisher.publishEvent(new CacheInvalidationEvent(this, cacheName, null));
    }
}

// 缓存监听器
@Component
public class CacheInvalidationListener {
    
    @EventListener
    public void onCacheInvalidation(CacheInvalidationEvent event) {
        String cacheName = event.getCacheName();
        Object key = event.getKey();
        
        if (key == null) {
            System.out.println("缓存全量失效: " + cacheName);
        } else {
            System.out.println("缓存条目失效: " + cacheName + "." + key);
        }
        
        // 可以执行额外的操作,如通知其他节点
    }
}

五、总结与最佳实践

最佳实践

  1. 事件设计

    • 事件类名以 Event 结尾
    • 包含必要的业务数据
    • 避免包含大对象
  2. 事件发布

    • 在业务逻辑完成后发布
    • 考虑事务边界
    • 避免循环发布
  3. 事件监听

    • 优先使用 @EventListener
    • 异步处理耗时操作
    • 处理好异常
  4. 事务事件

    • 使用 @TransactionalEventListener
    • 选择合适的 phase
    • 确保幂等性

注意事项

  1. 同步 vs 异步

    • 同步:保证顺序,但有性能影响
    • 异步:提高性能,但可能丢失事件
  2. 异常处理

    • 监听器异常不会影响发布者
    • 异步监听器需要自行处理异常
  3. 循环依赖

    • 避免事件循环发布
    • 监听器不要再发布同类事件

Spring 事件机制是实现业务解耦的强大工具,合理使用事件驱动模式,能够使系统更加灵活、可维护。理解事件的生命周期和传播机制,选择合适的监听方式,是使用好这一机制的关键。