Spring Boot 事件发布与监听 观察者模式的实际应用
文章目录
- 一、核心概念
- 1.1 事件模型组成
- 1.2 核心接口
- 二、实现方案
- 1. 创建自定义事件
- 2. 创建事件监听器
- 方式1:实现 ApplicationListener 接口
- 方式2:使用 @EventListener 注解(推荐)
- 3. 发布事件
- 三、高级特性
- 3.1 异步事件处理
- 3.2 事务绑定事件
- 3.3 条件事件监听
- 3.4 事件处理顺序控制
- 四、注意事项
- 五、完整示例:用户注册流程
- 六、总结
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;}// Getterspublic 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;}// Getterspublic 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<UserRegisteredEvent> {@Overridepublic void onApplicationEvent(UserRegisteredEvent event) {System.out.println("发送欢迎邮件给: " + event.getEmail());// 实际邮件发送逻辑}
}@Component
public class OrderProcessingListener implements ApplicationListener<OrderCreatedEvent> {@Overridepublic 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 {// 监听用户注册事件@EventListenerpublic void handleUserRegistered(UserRegisteredEvent event) {System.out.println("记录用户注册日志: " + event.getUsername());// 日志记录逻辑}// 监听订单创建事件(异步执行)@Async@EventListenerpublic 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") // 指定线程池@EventListenerpublic 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)@EventListenerpublic void firstListener(UserRegisteredEvent event) {System.out.println("第一个监听器执行");}@Order(2)@EventListenerpublic void secondListener(UserRegisteredEvent event) {System.out.println("第二个监听器执行");}@Order(Ordered.LOWEST_PRECEDENCE) // 最低优先级@EventListenerpublic 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;}@Transactionalpublic 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@EventListenerpublic void sendWelcomeEmail(UserRegisteredEvent event) {User user = event.getUser();emailService.sendWelcomeEmail(user.getEmail(), user.getUsername());}// 初始化用户资料@EventListenerpublic 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 事件机制提供了强大的解耦能力,通过事件驱动架构可以实现:
- 业务解耦:分离核心业务与辅助功能
- 可扩展性:轻松添加新功能而不修改现有代码
- 异步处理:提高系统响应速度
- 事务管理:精确控制事件处理时机
在实际应用中,应根据业务需求合理选择同步/异步处理、事务绑定等特性,并注意事件对象的合理设计和错误处理机制。