Spring事件机制详解:从原理到实战
前言
Spring事件机制是基于观察者模式实现的一套事件驱动架构,它允许应用程序中的不同组件之间进行松耦合的通信。通过事件机制,我们可以将业务逻辑解耦,提高代码的可维护性和可扩展性。本文将深入讲解Spring事件机制的核心概念、实现原理和实战应用。
一、事件机制概述
1.1 什么是事件驱动
事件驱动编程是一种编程范式,程序的执行流程由事件来决定。当某个事件发生时,会触发相应的事件处理器来执行特定的操作。
vbnet
传统调用 vs 事件驱动
┌─────────────────────────────────────────┐
│ 传统调用(紧耦合) │
│ ┌──────────┐ │
│ │UserService│ │
│ └─────┬────┘ │
│ │ 直接调用 │
│ ├─────────> EmailService │
│ ├─────────> SmsService │
│ ├─────────> CouponService │
│ └─────────> LogService │
│ │
│ 问题:UserService需要知道所有依赖 │
├─────────────────────────────────────────┤
│ 事件驱动(松耦合) │
│ ┌──────────┐ Event │
│ │UserService├───────> EventBus │
│ └──────────┘ │ │
│ │ │
│ ┌────────────────┼────────────┐ │
│ ▼ ▼ ▼ │
│ EmailService SmsService CouponService
│ │
│ 优势:各组件独立,互不影响 │
└─────────────────────────────────────────┘
1.2 Spring事件机制核心组件
Spring事件机制核心组件
┌─────────────────────────────────────────┐
│ ApplicationEvent(事件) │
│ - Spring事件的基类 │
│ - 携带事件相关数据 │
├─────────────────────────────────────────┤
│ ApplicationListener(监听器) │
│ - 事件监听接口 │
│ - 处理特定类型的事件 │
├─────────────────────────────────────────┤
│ ApplicationEventPublisher(发布器) │
│ - 事件发布接口 │
│ - ApplicationContext实现了该接口 │
├─────────────────────────────────────────┤
│ ApplicationEventMulticaster(广播器) │
│ - 事件广播器 │
│ - 负责将事件分发给所有监听器 │
└─────────────────────────────────────────┘
1.3 事件机制工作流程
scss
事件发布与监听流程
┌──────────────┐
│ 发布事件 │
│ publishEvent│
└──────┬───────┘
│
▼
┌─────────────────────────────┐
│ ApplicationEventPublisher │
└──────┬──────────────────────┘
│
▼
┌─────────────────────────────┐
│ ApplicationEventMulticaster │
│ (事件广播器) │
└──────┬──────────────────────┘
│
├──────────────────────────┐
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Listener1 │ │ Listener2 │
│ onEvent() │ │ onEvent() │
└─────────────┘ └─────────────┘
二、Spring事件基础
2.1 创建自定义事件
java
/**
* 自定义事件 - 用户注册事件
*/
public class UserRegisterEvent extends ApplicationEvent {
private User user;
private String registerIp;
private LocalDateTime registerTime;
public UserRegisterEvent(Object source, User user, String registerIp) {
super(source);
this.user = user;
this.registerIp = registerIp;
this.registerTime = LocalDateTime.now();
}
public User getUser() {
return user;
}
public String getRegisterIp() {
return registerIp;
}
public LocalDateTime getRegisterTime() {
return registerTime;
}
}
/**
* 用户实体
*/
@Data
@AllArgsConstructor
public class User {
private Long id;
private String username;
private String email;
private String phone;
}
2.2 创建事件监听器
方式一:实现ApplicationListener接口
java
/**
* 方式1:实现ApplicationListener接口
*/
@Component
public class UserRegisterListener implements ApplicationListener<UserRegisterEvent> {
private static final Logger log = LoggerFactory.getLogger(UserRegisterListener.class);
@Override
public void onApplicationEvent(UserRegisterEvent event) {
User user = event.getUser();
log.info("用户注册监听器收到事件: 用户[{}]于{}注册,IP: {}",
user.getUsername(),
event.getRegisterTime(),
event.getRegisterIp());
// 处理用户注册后的业务逻辑
sendWelcomeEmail(user);
}
private void sendWelcomeEmail(User user) {
log.info("发送欢迎邮件给: {}", user.getEmail());
}
}
方式二:使用@EventListener注解
java
/**
* 方式2:使用@EventListener注解(推荐)
*/
@Component
@Slf4j
public class UserRegisterEventHandler {
/**
* 发送欢迎邮件
*/
@EventListener
public void handleWelcomeEmail(UserRegisterEvent event) {
User user = event.getUser();
log.info("发送欢迎邮件给: {}", user.getEmail());
// 模拟发送邮件
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 赠送新人优惠券
*/
@EventListener
public void handleNewUserCoupon(UserRegisterEvent event) {
User user = event.getUser();
log.info("为新用户[{}]赠送优惠券", user.getUsername());
// 模拟赠送优惠券
grantCoupon(user);
}
/**
* 记录注册日志
*/
@EventListener
public void handleRegisterLog(UserRegisterEvent event) {
User user = event.getUser();
log.info("记录用户注册日志: 用户[{}], IP[{}], 时间[{}]",
user.getUsername(),
event.getRegisterIp(),
event.getRegisterTime());
}
private void grantCoupon(User user) {
// 优惠券发放逻辑
}
}
2.3 发布事件
java
/**
* 用户服务 - 发布事件
*/
@Service
@Slf4j
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private UserDao userDao;
/**
* 用户注册
*/
public void register(User user, String ip) {
// 1. 保存用户
userDao.save(user);
log.info("用户保存成功: {}", user.getUsername());
// 2. 发布用户注册事件
UserRegisterEvent event = new UserRegisterEvent(this, user, ip);
eventPublisher.publishEvent(event);
log.info("用户注册事件已发布");
// 3. 后续逻辑不需要关心事件的处理
}
}
2.4 完整示例
java
/**
* 测试类
*/
@SpringBootTest
public class EventTest {
@Autowired
private UserService userService;
@Test
public void testUserRegister() {
User user = new User(1L, "zhangsan", "zhangsan@example.com", "13800138000");
userService.register(user, "192.168.1.100");
}
}
/**
* 控制台输出:
* 用户保存成功: zhangsan
* 用户注册事件已发布
* 发送欢迎邮件给: zhangsan@example.com
* 为新用户[zhangsan]赠送优惠券
* 记录用户注册日志: 用户[zhangsan], IP[192.168.1.100], 时间[2024-01-01T10:00:00]
*/
三、高级特性
3.1 条件监听
java
/**
* 条件监听 - 使用SpEL表达式
*/
@Component
@Slf4j
public class ConditionalEventListener {
/**
* 只处理来自北京的用户注册
*/
@EventListener(condition = "#event.registerIp.startsWith('110')")
public void handleBeijingUser(UserRegisterEvent event) {
log.info("北京用户注册: {}", event.getUser().getUsername());
}
/**
* 只处理邮箱为gmail的用户
*/
@EventListener(condition = "#event.user.email.contains('gmail')")
public void handleGmailUser(UserRegisterEvent event) {
log.info("Gmail用户注册: {}", event.getUser().getEmail());
}
/**
* 用户ID大于100的注册事件
*/
@EventListener(condition = "#event.user.id > 100")
public void handleVIPUser(UserRegisterEvent event) {
log.info("VIP用户注册: {}", event.getUser().getId());
}
}
3.2 异步事件监听
java
/**
* 启用异步支持
*/
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public ThreadPoolTaskExecutor asyncEventExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(100);
executor.setThreadNamePrefix("async-event-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
/**
* 异步事件监听器
*/
@Component
@Slf4j
public class AsyncEventListener {
/**
* 异步发送欢迎邮件
*/
@Async("asyncEventExecutor")
@EventListener
public void handleWelcomeEmailAsync(UserRegisterEvent event) {
log.info("异步线程[{}]发送欢迎邮件", Thread.currentThread().getName());
// 模拟耗时操作
try {
Thread.sleep(2000);
log.info("欢迎邮件发送完成: {}", event.getUser().getEmail());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 异步发送短信通知
*/
@Async("asyncEventExecutor")
@EventListener
public void handleSmsAsync(UserRegisterEvent event) {
log.info("异步线程[{}]发送短信", Thread.currentThread().getName());
try {
Thread.sleep(1000);
log.info("短信发送完成: {}", event.getUser().getPhone());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3.3 事件监听顺序
java
/**
* 使用@Order控制监听器执行顺序
*/
@Component
@Slf4j
@Order(1) // 数字越小,优先级越高
public class FirstEventListener {
@EventListener
public void handle(UserRegisterEvent event) {
log.info("第一个监听器执行");
}
}
@Component
@Slf4j
@Order(2)
public class SecondEventListener {
@EventListener
public void handle(UserRegisterEvent event) {
log.info("第二个监听器执行");
}
}
@Component
@Slf4j
@Order(3)
public class ThirdEventListener {
@EventListener
public void handle(UserRegisterEvent event) {
log.info("第三个监听器执行");
}
}
3.4 泛型事件
java
/**
* 泛型事件基类
*/
public class EntityEvent<T> extends ApplicationEvent {
private T entity;
private EventType eventType;
public EntityEvent(Object source, T entity, EventType eventType) {
super(source);
this.entity = entity;
this.eventType = eventType;
}
public T getEntity() {
return entity;
}
public EventType getEventType() {
return eventType;
}
public enum EventType {
CREATE, UPDATE, DELETE
}
}
/**
* 泛型事件监听器
*/
@Component
@Slf4j
public class GenericEventListener {
/**
* 监听User实体事件
*/
@EventListener
public void handleUserEvent(EntityEvent<User> event) {
User user = event.getEntity();
EventType type = event.getEventType();
log.info("User实体事件: {}, 用户: {}", type, user.getUsername());
}
/**
* 监听Product实体事件
*/
@EventListener
public void handleProductEvent(EntityEvent<Product> event) {
Product product = event.getEntity();
EventType type = event.getEventType();
log.info("Product实体事件: {}, 商品: {}", type, product.getName());
}
}
/**
* 使用泛型事件
*/
@Service
public class GenericEventService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createUser(User user) {
// 创建用户
// ...
// 发布创建事件
eventPublisher.publishEvent(
new EntityEvent<>(this, user, EntityEvent.EventType.CREATE)
);
}
public void updateProduct(Product product) {
// 更新商品
// ...
// 发布更新事件
eventPublisher.publishEvent(
new EntityEvent<>(this, product, EntityEvent.EventType.UPDATE)
);
}
}
3.5 事务事件监听
java
/**
* 事务事件监听器
* @TransactionalEventListener可以在事务的不同阶段触发
*/
@Component
@Slf4j
public class TransactionalEventListener {
/**
* 事务提交后执行(默认)
*/
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(UserRegisterEvent event) {
log.info("事务提交后执行: {}", event.getUser().getUsername());
// 发送通知邮件等操作
}
/**
* 事务回滚后执行
*/
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void handleAfterRollback(UserRegisterEvent event) {
log.info("事务回滚后执行: {}", event.getUser().getUsername());
// 记录失败日志
}
/**
* 事务完成后执行(无论提交还是回滚)
*/
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
public void handleAfterCompletion(UserRegisterEvent event) {
log.info("事务完成后执行: {}", event.getUser().getUsername());
// 清理资源
}
/**
* 事务提交前执行
*/
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleBeforeCommit(UserRegisterEvent event) {
log.info("事务提交前执行: {}", event.getUser().getUsername());
// 数据校验
}
}
/**
* 带事务的服务
*/
@Service
public class TransactionalUserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private UserDao userDao;
@Transactional
public void registerWithTransaction(User user, String ip) {
// 保存用户
userDao.save(user);
// 发布事件
eventPublisher.publishEvent(new UserRegisterEvent(this, user, ip));
// 如果后续代码抛出异常,事务回滚
// 监听器的执行时机取决于@TransactionalEventListener的phase配置
}
}
四、实战案例
4.1 案例1:订单状态变更通知
java
/**
* 订单状态变更事件
*/
public class OrderStatusChangeEvent extends ApplicationEvent {
private Order order;
private OrderStatus oldStatus;
private OrderStatus newStatus;
public OrderStatusChangeEvent(Object source, Order order,
OrderStatus oldStatus, OrderStatus newStatus) {
super(source);
this.order = order;
this.oldStatus = oldStatus;
this.newStatus = newStatus;
}
public Order getOrder() { return order; }
public OrderStatus getOldStatus() { return oldStatus; }
public OrderStatus getNewStatus() { return newStatus; }
}
/**
* 订单实体
*/
@Data
public class Order {
private Long id;
private String orderNo;
private Long userId;
private BigDecimal amount;
private OrderStatus status;
}
/**
* 订单状态枚举
*/
public enum OrderStatus {
PENDING("待支付"),
PAID("已支付"),
SHIPPED("已发货"),
COMPLETED("已完成"),
CANCELLED("已取消");
private String description;
OrderStatus(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
/**
* 订单状态变更监听器
*/
@Component
@Slf4j
public class OrderStatusEventListener {
@Autowired
private NotificationService notificationService;
@Autowired
private InventoryService inventoryService;
/**
* 订单支付成功 - 发送通知
*/
@EventListener(condition = "#event.newStatus.name() == 'PAID'")
public void handleOrderPaid(OrderStatusChangeEvent event) {
Order order = event.getOrder();
log.info("订单已支付: {}", order.getOrderNo());
// 发送支付成功通知
notificationService.sendOrderPaidNotification(order);
}
/**
* 订单发货 - 更新库存
*/
@EventListener(condition = "#event.newStatus.name() == 'SHIPPED'")
public void handleOrderShipped(OrderStatusChangeEvent event) {
Order order = event.getOrder();
log.info("订单已发货: {}", order.getOrderNo());
// 扣减库存
inventoryService.deductInventory(order);
// 发送发货通知
notificationService.sendShippingNotification(order);
}
/**
* 订单取消 - 退款处理
*/
@EventListener(condition = "#event.newStatus.name() == 'CANCELLED'")
public void handleOrderCancelled(OrderStatusChangeEvent event) {
Order order = event.getOrder();
OrderStatus oldStatus = event.getOldStatus();
log.info("订单已取消: {}, 原状态: {}", order.getOrderNo(), oldStatus);
// 如果已支付,需要退款
if (oldStatus == OrderStatus.PAID || oldStatus == OrderStatus.SHIPPED) {
processRefund(order);
}
}
/**
* 订单完成 - 增加积分
*/
@EventListener(condition = "#event.newStatus.name() == 'COMPLETED'")
public void handleOrderCompleted(OrderStatusChangeEvent event) {
Order order = event.getOrder();
log.info("订单已完成: {}", order.getOrderNo());
// 增加用户积分
addUserPoints(order);
// 请求用户评价
notificationService.requestReview(order);
}
private void processRefund(Order order) {
log.info("处理退款: 订单{}, 金额{}", order.getOrderNo(), order.getAmount());
}
private void addUserPoints(Order order) {
int points = order.getAmount().intValue();
log.info("为用户{}增加{}积分", order.getUserId(), points);
}
}
/**
* 订单服务
*/
@Service
@Slf4j
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private OrderDao orderDao;
/**
* 更新订单状态
*/
@Transactional
public void updateOrderStatus(Long orderId, OrderStatus newStatus) {
// 查询订单
Order order = orderDao.findById(orderId);
OrderStatus oldStatus = order.getStatus();
// 更新状态
order.setStatus(newStatus);
orderDao.update(order);
log.info("订单状态更新: {} -> {}", oldStatus, newStatus);
// 发布状态变更事件
OrderStatusChangeEvent event = new OrderStatusChangeEvent(
this, order, oldStatus, newStatus
);
eventPublisher.publishEvent(event);
}
}
4.2 案例2:系统监控告警
java
/**
* 系统监控事件
*/
public class SystemMonitorEvent extends ApplicationEvent {
private MonitorType type;
private String message;
private Map<String, Object> metrics;
private AlertLevel level;
public SystemMonitorEvent(Object source, MonitorType type,
String message, AlertLevel level) {
super(source);
this.type = type;
this.message = message;
this.level = level;
this.metrics = new HashMap<>();
}
public void addMetric(String key, Object value) {
metrics.put(key, value);
}
// Getters
public MonitorType getType() { return type; }
public String getMessage() { return message; }
public AlertLevel getLevel() { return level; }
public Map<String, Object> getMetrics() { return metrics; }
}
/**
* 监控类型
*/
public enum MonitorType {
CPU_USAGE, // CPU使用率
MEMORY_USAGE, // 内存使用率
DISK_USAGE, // 磁盘使用率
API_ERROR, // API错误
SLOW_QUERY // 慢查询
}
/**
* 告警级别
*/
public enum AlertLevel {
INFO, WARNING, ERROR, CRITICAL
}
/**
* 系统监控监听器
*/
@Component
@Slf4j
public class SystemMonitorListener {
@Autowired
private EmailService emailService;
@Autowired
private SmsService smsService;
@Autowired
private DingTalkService dingTalkService;
/**
* 严重告警 - 多渠道通知
*/
@EventListener(condition = "#event.level.name() == 'CRITICAL'")
public void handleCriticalAlert(SystemMonitorEvent event) {
log.error("严重告警: {} - {}", event.getType(), event.getMessage());
// 发送邮件
emailService.sendAlert("严重告警", formatAlertMessage(event));
// 发送短信
smsService.sendAlert(formatAlertMessage(event));
// 发送钉钉通知
dingTalkService.sendAlert(formatAlertMessage(event));
}
/**
* 错误告警 - 邮件+钉钉通知
*/
@EventListener(condition = "#event.level.name() == 'ERROR'")
public void handleErrorAlert(SystemMonitorEvent event) {
log.error("错误告警: {} - {}", event.getType(), event.getMessage());
emailService.sendAlert("错误告警", formatAlertMessage(event));
dingTalkService.sendAlert(formatAlertMessage(event));
}
/**
* 警告告警 - 钉钉通知
*/
@EventListener(condition = "#event.level.name() == 'WARNING'")
public void handleWarningAlert(SystemMonitorEvent event) {
log.warn("警告告警: {} - {}", event.getType(), event.getMessage());
dingTalkService.sendAlert(formatAlertMessage(event));
}
/**
* CPU使用率告警 - 特殊处理
*/
@EventListener(condition = "#event.type.name() == 'CPU_USAGE'")
public void handleCpuUsageAlert(SystemMonitorEvent event) {
log.info("CPU使用率告警: {}", event.getMessage());
// 记录CPU使用率历史
saveCpuUsageHistory(event);
// 尝试自动扩容
if (event.getLevel() == AlertLevel.CRITICAL) {
tryAutoScale();
}
}
private String formatAlertMessage(SystemMonitorEvent event) {
StringBuilder sb = new StringBuilder();
sb.append("告警类型: ").append(event.getType()).append("\n");
sb.append("告警级别: ").append(event.getLevel()).append("\n");
sb.append("告警信息: ").append(event.getMessage()).append("\n");
sb.append("指标数据: ").append(event.getMetrics()).append("\n");
sb.append("时间: ").append(LocalDateTime.now()).append("\n");
return sb.toString();
}
private void saveCpuUsageHistory(SystemMonitorEvent event) {
// 保存CPU使用率历史数据
}
private void tryAutoScale() {
log.info("尝试自动扩容...");
// 触发自动扩容逻辑
}
}
/**
* 系统监控服务
*/
@Service
@Slf4j
public class SystemMonitorService {
@Autowired
private ApplicationEventPublisher eventPublisher;
/**
* 监控CPU使用率
*/
@Scheduled(fixedRate = 60000) // 每分钟检查一次
public void monitorCpuUsage() {
double cpuUsage = getCpuUsage();
if (cpuUsage > 90) {
publishAlert(MonitorType.CPU_USAGE,
"CPU使用率过高: " + cpuUsage + "%",
AlertLevel.CRITICAL,
"cpuUsage", cpuUsage);
} else if (cpuUsage > 80) {
publishAlert(MonitorType.CPU_USAGE,
"CPU使用率较高: " + cpuUsage + "%",
AlertLevel.WARNING,
"cpuUsage", cpuUsage);
}
}
/**
* 监控API错误率
*/
public void reportApiError(String api, Exception e) {
publishAlert(MonitorType.API_ERROR,
"API调用失败: " + api + ", 错误: " + e.getMessage(),
AlertLevel.ERROR,
"api", api,
"error", e.getMessage());
}
private void publishAlert(MonitorType type, String message,
AlertLevel level, Object... metrics) {
SystemMonitorEvent event = new SystemMonitorEvent(this, type, message, level);
// 添加指标数据
for (int i = 0; i < metrics.length; i += 2) {
event.addMetric((String) metrics[i], metrics[i + 1]);
}
eventPublisher.publishEvent(event);
}
private double getCpuUsage() {
// 获取CPU使用率
return Math.random() * 100;
}
}
4.3 案例3:数据变更审计
java
/**
* 数据变更事件
*/
public class DataChangeEvent extends ApplicationEvent {
private String entityType;
private Long entityId;
private OperationType operationType;
private Map<String, Object> oldValues;
private Map<String, Object> newValues;
private String operator;
public DataChangeEvent(Object source, String entityType, Long entityId,
OperationType operationType, String operator) {
super(source);
this.entityType = entityType;
this.entityId = entityId;
this.operationType = operationType;
this.operator = operator;
this.oldValues = new HashMap<>();
this.newValues = new HashMap<>();
}
public void addChange(String field, Object oldValue, Object newValue) {
oldValues.put(field, oldValue);
newValues.put(field, newValue);
}
// Getters
public String getEntityType() { return entityType; }
public Long getEntityId() { return entityId; }
public OperationType getOperationType() { return operationType; }
public Map<String, Object> getOldValues() { return oldValues; }
public Map<String, Object> getNewValues() { return newValues; }
public String getOperator() { return operator; }
}
/**
* 操作类型
*/
public enum OperationType {
CREATE, UPDATE, DELETE
}
/**
* 审计日志实体
*/
@Data
public class AuditLog {
private Long id;
private String entityType;
private Long entityId;
private String operationType;
private String changes;
private String operator;
private LocalDateTime createTime;
}
/**
* 数据变更审计监听器
*/
@Component
@Slf4j
public class DataChangeAuditListener {
@Autowired
private AuditLogService auditLogService;
/**
* 记录所有数据变更
*/
@Async
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleDataChange(DataChangeEvent event) {
log.info("记录数据变更审计: {} {} {}",
event.getOperationType(),
event.getEntityType(),
event.getEntityId());
// 创建审计日志
AuditLog auditLog = new AuditLog();
auditLog.setEntityType(event.getEntityType());
auditLog.setEntityId(event.getEntityId());
auditLog.setOperationType(event.getOperationType().name());
auditLog.setOperator(event.getOperator());
auditLog.setCreateTime(LocalDateTime.now());
// 记录变更内容
Map<String, Object> changes = new HashMap<>();
changes.put("old", event.getOldValues());
changes.put("new", event.getNewValues());
auditLog.setChanges(JSON.toJSONString(changes));
// 保存审计日志
auditLogService.save(auditLog);
}
/**
* 敏感数据变更 - 额外通知
*/
@EventListener(condition = "#event.entityType == 'User' && " +
"#event.newValues.containsKey('role')")
public void handleSensitiveChange(DataChangeEvent event) {
log.warn("敏感数据变更: 用户[{}]的角色被[{}]修改",
event.getEntityId(),
event.getOperator());
// 发送安全通知
sendSecurityAlert(event);
}
private void sendSecurityAlert(DataChangeEvent event) {
// 发送安全告警
}
}
/**
* 用户服务 - 发布数据变更事件
*/
@Service
@Slf4j
public class UserAuditService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private UserDao userDao;
@Transactional
public void updateUser(Long userId, User newUser, String operator) {
// 查询旧数据
User oldUser = userDao.findById(userId);
// 更新数据
userDao.update(newUser);
// 发布数据变更事件
DataChangeEvent event = new DataChangeEvent(
this, "User", userId, OperationType.UPDATE, operator
);
// 记录变更字段
if (!Objects.equals(oldUser.getUsername(), newUser.getUsername())) {
event.addChange("username", oldUser.getUsername(), newUser.getUsername());
}
if (!Objects.equals(oldUser.getEmail(), newUser.getEmail())) {
event.addChange("email", oldUser.getEmail(), newUser.getEmail());
}
eventPublisher.publishEvent(event);
}
}
4.4 案例4:分布式事件总线
java
/**
* 分布式事件(通过消息队列)
*/
public class DistributedEvent implements Serializable {
private String eventId;
private String eventType;
private String source;
private Map<String, Object> payload;
private LocalDateTime timestamp;
public DistributedEvent(String eventType, String source) {
this.eventId = UUID.randomUUID().toString();
this.eventType = eventType;
this.source = source;
this.payload = new HashMap<>();
this.timestamp = LocalDateTime.now();
}
public void addPayload(String key, Object value) {
payload.put(key, value);
}
// Getters and Setters
}
/**
* 分布式事件发布器
*/
@Service
@Slf4j
public class DistributedEventPublisher {
@Autowired
private RabbitTemplate rabbitTemplate;
private static final String EXCHANGE = "event.exchange";
/**
* 发布分布式事件
*/
public void publish(DistributedEvent event) {
String routingKey = "event." + event.getEventType();
log.info("发布分布式事件: {} -> {}", event.getEventType(), routingKey);
rabbitTemplate.convertAndSend(EXCHANGE, routingKey, event);
}
/**
* 发布用户注册事件(分布式)
*/
public void publishUserRegister(User user) {
DistributedEvent event = new DistributedEvent("user.register", "user-service");
event.addPayload("userId", user.getId());
event.addPayload("username", user.getUsername());
event.addPayload("email", user.getEmail());
publish(event);
}
/**
* 发布订单创建事件(分布式)
*/
public void publishOrderCreated(Order order) {
DistributedEvent event = new DistributedEvent("order.created", "order-service");
event.addPayload("orderId", order.getId());
event.addPayload("orderNo", order.getOrderNo());
event.addPayload("amount", order.getAmount());
publish(event);
}
}
/**
* 分布式事件监听器
*/
@Component
@Slf4j
public class DistributedEventListener {
/**
* 监听用户注册事件
*/
@RabbitListener(queues = "user.register.queue")
public void handleUserRegister(DistributedEvent event) {
log.info("收到用户注册事件: {}", event.getEventId());
Long userId = (Long) event.getPayload().get("userId");
String email = (String) event.getPayload().get("email");
// 处理用户注册后的业务
sendWelcomeEmail(email);
}
/**
* 监听订单创建事件
*/
@RabbitListener(queues = "order.created.queue")
public void handleOrderCreated(DistributedEvent event) {
log.info("收到订单创建事件: {}", event.getEventId());
String orderNo = (String) event.getPayload().get("orderNo");
// 处理订单创建后的业务
processOrderCreated(orderNo);
}
private void sendWelcomeEmail(String email) {
log.info("发送欢迎邮件: {}", email);
}
private void processOrderCreated(String orderNo) {
log.info("处理订单创建: {}", orderNo);
}
}
五、Spring内置事件
5.1 容器生命周期事件
java
/**
* 监听Spring容器生命周期事件
*/
@Component
@Slf4j
public class ApplicationLifecycleListener {
/**
* 容器刷新事件
*/
@EventListener
public void handleContextRefreshed(ContextRefreshedEvent event) {
log.info("容器刷新完成");
ApplicationContext context = event.getApplicationContext();
log.info("Bean数量: {}", context.getBeanDefinitionCount());
}
/**
* 容器启动事件
*/
@EventListener
public void handleContextStarted(ContextStartedEvent event) {
log.info("容器启动");
}
/**
* 容器停止事件
*/
@EventListener
public void handleContextStopped(ContextStoppedEvent event) {
log.info("容器停止");
// 清理资源
}
/**
* 容器关闭事件
*/
@EventListener
public void handleContextClosed(ContextClosedEvent event) {
log.info("容器关闭");
// 释放资源、保存状态等
}
}
5.2 Web应用事件
java
/**
* 监听Web应用事件
*/
@Component
@Slf4j
public class WebApplicationListener {
/**
* ServletContext初始化事件
*/
@EventListener
public void handleServletContextInitialized(ServletRequestHandledEvent event) {
log.info("Servlet请求处理: {} {}, 耗时: {}ms",
event.getMethod(),
event.getRequestUrl(),
event.getProcessingTimeMillis());
}
}
六、最佳实践
6.1 事件设计原则
java
/**
* 1. 事件应该是不可变的
*/
public class ImmutableEvent extends ApplicationEvent {
private final String data;
private final LocalDateTime timestamp;
public ImmutableEvent(Object source, String data) {
super(source);
this.data = data;
this.timestamp = LocalDateTime.now();
}
// 只提供getter,不提供setter
public String getData() { return data; }
public LocalDateTime getTimestamp() { return timestamp; }
}
/**
* 2. 事件命名应该清晰表达意图
*/
// ✓ 好的命名
public class UserRegisteredEvent extends ApplicationEvent { }
public class OrderCancelledEvent extends ApplicationEvent { }
public class PaymentCompletedEvent extends ApplicationEvent { }
// ✗ 不好的命名
public class Event1 extends ApplicationEvent { }
public class UserEvent extends ApplicationEvent { }
/**
* 3. 监听器应该独立、无状态
*/
@Component
public class GoodListener {
@EventListener
public void handle(UserRegisterEvent event) {
// 处理逻辑独立,不依赖类成员变量
sendEmail(event.getUser().getEmail());
}
private void sendEmail(String email) {
// ...
}
}
6.2 异常处理
java
/**
* 事件监听器异常处理
*/
@Component
@Slf4j
public class SafeEventListener {
/**
* 捕获异常,避免影响其他监听器
*/
@EventListener
public void handleWithExceptionHandling(UserRegisterEvent event) {
try {
// 可能抛出异常的代码
sendEmail(event.getUser().getEmail());
} catch (Exception e) {
log.error("发送邮件失败", e);
// 记录错误,但不抛出,避免影响其他监听器
}
}
private void sendEmail(String email) throws Exception {
// 可能抛出异常
}
}
/**
* 自定义异常处理器
*/
@Component
public class CustomErrorHandler implements ErrorHandler {
private static final Logger log = LoggerFactory.getLogger(CustomErrorHandler.class);
@Override
public void handleError(Throwable t) {
log.error("事件监听器执行异常", t);
// 可以发送告警
}
}
/**
* 配置异步事件的异常处理器
*/
@Configuration
public class AsyncEventConfig {
@Bean
public SimpleApplicationEventMulticaster applicationEventMulticaster() {
SimpleApplicationEventMulticaster multicaster =
new SimpleApplicationEventMulticaster();
// 设置异常处理器
multicaster.setErrorHandler(new CustomErrorHandler());
return multicaster;
}
}
七、总结
核心知识点回顾
java
Spring事件机制核心要点
│
├── 基础组件
│ ├── ApplicationEvent(事件)
│ ├── ApplicationListener(监听器)
│ ├── ApplicationEventPublisher(发布器)
│ └── ApplicationEventMulticaster(广播器)
│
├── 监听方式
│ ├── 实现ApplicationListener接口
│ └── 使用@EventListener注解
│
├── 高级特性
│ ├── 条件监听(SpEL表达式)
│ ├── 异步监听(@Async)
│ ├── 监听顺序(@Order)
│ ├── 泛型事件
│ └── 事务事件(@TransactionalEventListener)
│
├── 实战应用
│ ├── 用户注册通知
│ ├── 订单状态变更
│ ├── 系统监控告警
│ ├── 数据变更审计
│ └── 分布式事件
│
└── 最佳实践
├── 事件不可变
├── 监听器独立
├── 异常处理
└── 异步执行耗时操作
Spring事件机制提供了一种优雅的方式来实现组件间的解耦通信。通过合理使用事件机制,可以让代码更加灵活、可维护,易于扩展。在实际项目中,事件机制广泛应用于用户行为追踪、系统监控、业务流程解耦等场景。