Spring Boot 事件发布与监听 观察者模式的实际应用 - 实践
文章目录
Spring Boot 提供了强大的事件发布与监听机制,基于观察者模式实现组件间的解耦通信。
一、核心概念
1.1 事件模型组成
- 事件(Event):需要传递的消息对象
- 发布者(Publisher):负责发布事件
- 监听器(Listener):订阅并处理事件
1.2 核心接口
ApplicationEvent:事件基类ApplicationEventPublisher:事件发布接口ApplicationListener:事件监听接口
二、实现方案
1. 创建自定义事件
import org.springframework.context.ApplicationEvent;
// 用户注册事件
public class UserRegisteredEvent extends ApplicationEvent {
private final String username;
private final String email;
public UserRegisteredEvent(Object source, String username, String email) {
super(source);
this.username = username;
this.email = email;
}
// Getters
public String getUsername() { return username; }
public String getEmail() { return email; }
}
// 订单创建事件
public class OrderCreatedEvent extends ApplicationEvent {
private final Long orderId;
private final BigDecimal amount;
public OrderCreatedEvent(Object source, Long orderId, BigDecimal amount) {
super(source);
this.orderId = orderId;
this.amount = amount;
}
// Getters
public Long getOrderId() { return orderId; }
public BigDecimal getAmount() { return amount; }
}
2. 创建事件监听器
方式1:实现 ApplicationListener 接口
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class EmailNotificationListener implements ApplicationListener {
@Override
public void onApplicationEvent(UserRegisteredEvent event) {
System.out.println("发送欢迎邮件给: " + event.getEmail());
// 实际邮件发送逻辑
}
}
@Component
public class OrderProcessingListener implements ApplicationListener {
@Override
public void onApplicationEvent(OrderCreatedEvent event) {
System.out.println("处理订单 #" + event.getOrderId());
// 订单处理逻辑
}
}
方式2:使用 @EventListener 注解(推荐)
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class CompositeEventListener {
// 监听用户注册事件
@EventListener
public void handleUserRegistered(UserRegisteredEvent event) {
System.out.println("记录用户注册日志: " + event.getUsername());
// 日志记录逻辑
}
// 监听订单创建事件(异步执行)
@Async
@EventListener
public void handleOrderCreatedAsync(OrderCreatedEvent event) {
System.out.println("异步处理订单 #" + event.getOrderId());
// 耗时操作
}
// 监听多个事件
@EventListener(classes = {UserRegisteredEvent.class, OrderCreatedEvent.class})
public void handleMultipleEvents(ApplicationEvent event) {
if (event instanceof UserRegisteredEvent) {
System.out.println("处理用户注册事件");
} else if (event instanceof OrderCreatedEvent) {
System.out.println("处理订单创建事件");
}
}
}
3. 发布事件
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final ApplicationEventPublisher eventPublisher;
public UserService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void registerUser(String username, String email) {
// 用户注册逻辑...
// 发布用户注册事件
eventPublisher.publishEvent(new UserRegisteredEvent(this, username, email));
}
}
@Service
public class OrderService {
private final ApplicationEventPublisher eventPublisher;
public OrderService(ApplicationEventPublisher eventPublisher) {
this.eventPublisher = eventPublisher;
}
public void createOrder(Long orderId, BigDecimal amount) {
// 订单创建逻辑...
// 发布订单创建事件
eventPublisher.publishEvent(new OrderCreatedEvent(this, orderId, amount));
}
}
三、高级特性
3.1 异步事件处理
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean(name = "eventTaskExecutor")
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("Event-Executor-");
return executor;
}
}
// 在监听器中使用
@Component
public class AsyncEventListener {
@Async("eventTaskExecutor") // 指定线程池
@EventListener
public void handleAsyncEvent(UserRegisteredEvent event) {
// 异步处理逻辑
}
}
3.2 事务绑定事件
import org.springframework.transaction.event.TransactionalEventListener;
import org.springframework.transaction.event.TransactionPhase;
@Component
public class TransactionalEventListener {
// 在事务提交后执行
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(OrderCreatedEvent event) {
System.out.println("事务提交后处理订单事件");
}
// 在事务回滚后执行
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void handleAfterRollback(OrderCreatedEvent event) {
System.out.println("事务回滚后处理订单事件");
}
}
3.3 条件事件监听
@Component
public class ConditionalEventListener {
@EventListener(condition = "#event.amount > 1000")
public void handleLargeOrder(OrderCreatedEvent event) {
System.out.println("处理大额订单: " + event.getOrderId());
}
@EventListener(condition = "#event.username.startsWith('admin')")
public void handleAdminUser(UserRegisteredEvent event) {
System.out.println("处理管理员用户注册: " + event.getUsername());
}
}
3.4 事件处理顺序控制
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
public class OrderedEventListeners {
@Order(1)
@EventListener
public void firstListener(UserRegisteredEvent event) {
System.out.println("第一个监听器执行");
}
@Order(2)
@EventListener
public void secondListener(UserRegisteredEvent event) {
System.out.println("第二个监听器执行");
}
@Order(Ordered.LOWEST_PRECEDENCE) // 最低优先级
@EventListener
public void lastListener(UserRegisteredEvent event) {
System.out.println("最后一个监听器执行");
}
}
四、注意事项
事件命名规范:
- 使用过去时态表示已完成的事件:
UserRegisteredEvent,OrderCreatedEvent - 保持事件类名清晰表达业务含义
- 使用过去时态表示已完成的事件:
事件内容设计:
- 包含足够的信息供监听器处理
- 避免包含大型对象或敏感数据
- 保持事件对象不可变
错误处理:
@EventListener public void handleEventWithError(UserRegisteredEvent event) { try { // 业务逻辑 } catch (Exception e) { // 记录错误并处理 System.err.println("处理事件失败: " + e.getMessage()); // 可选择重试或通知监控系统 } }性能优化:
- 对于耗时操作使用异步监听
- 根据业务需求合理设置线程池参数
- 避免在事件处理中执行阻塞操作
五、完整示例:用户注册流程
// 事件定义
public class UserRegisteredEvent extends ApplicationEvent {
private final User user;
public UserRegisteredEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() { return user; }
}
// 服务层
@Service
public class UserService {
private final ApplicationEventPublisher eventPublisher;
private final UserRepository userRepository;
public UserService(ApplicationEventPublisher eventPublisher,
UserRepository userRepository) {
this.eventPublisher = eventPublisher;
this.userRepository = userRepository;
}
@Transactional
public User registerUser(UserRegistrationDto dto) {
User user = new User(dto.getUsername(), dto.getEmail(), dto.getPassword());
user = userRepository.save(user);
// 发布用户注册事件
eventPublisher.publishEvent(new UserRegisteredEvent(this, user));
return user;
}
}
// 监听器
@Component
public class UserEventListeners {
// 发送欢迎邮件
@Async
@EventListener
public void sendWelcomeEmail(UserRegisteredEvent event) {
User user = event.getUser();
emailService.sendWelcomeEmail(user.getEmail(), user.getUsername());
}
// 初始化用户资料
@EventListener
public void initUserProfile(UserRegisteredEvent event) {
User user = event.getUser();
profileService.createDefaultProfile(user.getId());
}
// 记录注册日志
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void logUserRegistration(UserRegisteredEvent event) {
User user = event.getUser();
auditLogService.log(Action.REGISTER, user.getId(), "用户注册");
}
// 给推荐人奖励(条件监听)
@EventListener(condition = "#event.user.referrerId != null")
public void rewardReferrer(UserRegisteredEvent event) {
User user = event.getUser();
rewardService.giveReferralReward(user.getReferrerId(), user.getId());
}
}
六、总结
Spring Boot 事件机制提供了强大的解耦能力,通过事件驱动架构可以实现:
- 业务解耦:分离核心业务与辅助功能
- 可扩展性:轻松添加新功能而不修改现有代码
- 异步处理:提高系统响应速度
- 事务管理:精确控制事件处理时机
在实际应用中,应根据业务需求合理选择同步/异步处理、事务绑定等特性,并注意事件对象的合理设计和错误处理机制。
浙公网安备 33010602011771号