副标题:解耦神器,让组件间通信更优雅!🎯
🎬 开场:什么是事件机制?
传统方式 vs 事件机制
场景:用户注册后,需要发送邮件、短信、积分等
传统方式(紧耦合):
@Service
public class UserService {
@Autowired
private EmailService emailService;
@Autowired
private SmsService smsService;
@Autowired
private PointService pointService;
public void register(User user) {
// 保存用户
userMapper.insert(user);
// 发送邮件
emailService.sendWelcomeEmail(user);
// 发送短信
smsService.sendWelcomeSms(user);
// 赠送积分
pointService.givePoints(user);
// 如果需要添加新功能,必须修改这里 ❌
}
}
问题:
- UserService依赖太多服务
- 高耦合
- 难以扩展
事件机制(解耦):
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void register(User user) {
// 保存用户
userMapper.insert(user);
// 发布事件
eventPublisher.publishEvent(new UserRegisterEvent(user));
// 不关心后续处理 ✅
}
}
// 邮件服务监听事件
@Component
public class EmailListener {
@EventListener
public void handleUserRegister(UserRegisterEvent event) {
emailService.sendWelcomeEmail(event.getUser());
}
}
// 短信服务监听事件
@Component
public class SmsListener {
@EventListener
public void handleUserRegister(UserRegisterEvent event) {
smsService.sendWelcomeSms(event.getUser());
}
}
优点:
- UserService只关心发布事件
- 低耦合
- 易于扩展(添加监听器即可)✅
📚 Spring事件机制组成
核心组件
Spring事件机制(4个核心):
1. ApplicationEvent(事件)
- 自定义事件类
- 继承ApplicationEvent
2. ApplicationEventPublisher(事件发布器)
- 发布事件
- publishEvent()方法
3. ApplicationListener(事件监听器)
- 监听事件
- onApplicationEvent()方法
4. ApplicationEventMulticaster(事件多播器)
- 管理监听器
- 广播事件
🎯 基本使用
1️⃣ 定义事件
/**
* 用户注册事件
*/
public class UserRegisterEvent extends ApplicationEvent {
private User user;
public UserRegisterEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
/**
* Spring 4.2+:不继承ApplicationEvent也可以
*/
public class OrderCreatedEvent {
private Order order;
public OrderCreatedEvent(Order order) {
this.order = order;
}
public Order getOrder() {
return order;
}
}
2️⃣ 发布事件
/**
* 发布事件的方式
*/
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher; // 方式1:注入发布器
// 或者
@Autowired
private ApplicationContext applicationContext; // 方式2:注入容器
/**
* 用户注册
*/
public void register(User user) {
// 保存用户
userMapper.insert(user);
// 方式1:使用ApplicationEventPublisher
eventPublisher.publishEvent(new UserRegisterEvent(this, user));
// 方式2:使用ApplicationContext
// applicationContext.publishEvent(new UserRegisterEvent(this, user));
System.out.println("用户注册完成");
}
}
3️⃣ 监听事件
/**
* 监听事件的方式
*/
// 方式1:实现ApplicationListener接口
@Component
public class UserRegisterListener implements ApplicationListener<UserRegisterEvent> {
@Override
public void onApplicationEvent(UserRegisterEvent event) {
User user = event.getUser();
System.out.println("监听到用户注册事件:" + user.getUsername());
// 处理业务逻辑
}
}
// 方式2:使用@EventListener注解(推荐)
@Component
public class EmailListener {
@EventListener
public void handleUserRegister(UserRegisterEvent event) {
User user = event.getUser();
System.out.println("发送欢迎邮件:" + user.getEmail());
// 发送邮件
emailService.sendWelcomeEmail(user);
}
}
@Component
public class SmsListener {
@EventListener
public void handleUserRegister(UserRegisterEvent event) {
User user = event.getUser();
System.out.println("发送欢迎短信:" + user.getPhone());
// 发送短信
smsService.sendWelcomeSms(user);
}
}
🔍 高级特性
条件监听
/**
* 条件监听:只在特定条件下触发
*/
@Component
public class ConditionalListener {
/**
* 只监听VIP用户的注册事件
*/
@EventListener(condition = "#event.user.vip == true")
public void handleVipRegister(UserRegisterEvent event) {
System.out.println("VIP用户注册");
// VIP专属处理
}
/**
* 只监听订单金额大于1000的事件
*/
@EventListener(condition = "#event.order.amount > 1000")
public void handleLargeOrder(OrderCreatedEvent event) {
System.out.println("大额订单");
// 大额订单特殊处理
}
}
异步监听
/**
* 异步监听事件
*/
@Configuration
@EnableAsync // 启用异步
public class AsyncConfig {
}
@Component
public class AsyncListener {
/**
* 异步监听
*/
@Async
@EventListener
public void handleUserRegister(UserRegisterEvent event) {
System.out.println("异步处理,线程:" + Thread.currentThread().getName());
// 耗时操作(不阻塞主线程)
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("异步处理完成");
}
}
事件监听顺序
/**
* 指定监听器执行顺序
*/
@Component
public class OrderedListener {
@EventListener
@Order(1) // 优先级1(数字越小优先级越高)
public void listener1(UserRegisterEvent event) {
System.out.println("监听器1执行");
}
@EventListener
@Order(2) // 优先级2
public void listener2(UserRegisterEvent event) {
System.out.println("监听器2执行");
}
@EventListener
@Order(3) // 优先级3
public void listener3(UserRegisterEvent event) {
System.out.println("监听器3执行");
}
}
/**
* 输出:
* 监听器1执行
* 监听器2执行
* 监听器3执行
*/
事务监听
/**
* 事务监听:在事务的特定阶段执行
*/
@Component
public class TransactionalListener {
/**
* 事务提交后执行
*/
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void afterCommit(UserRegisterEvent event) {
System.out.println("事务提交后:发送通知");
// 事务成功提交后才发送通知
notificationService.send(event.getUser());
}
/**
* 事务回滚后执行
*/
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void afterRollback(UserRegisterEvent event) {
System.out.println("事务回滚后:记录日志");
// 事务回滚后记录日志
logService.log("用户注册失败");
}
/**
* 事务完成后执行(无论提交还是回滚)
*/
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
public void afterCompletion(UserRegisterEvent event) {
System.out.println("事务完成后:清理资源");
}
}
/**
* 事务阶段:
* - BEFORE_COMMIT:事务提交前
* - AFTER_COMMIT:事务提交后(默认)
* - AFTER_ROLLBACK:事务回滚后
* - AFTER_COMPLETION:事务完成后(提交或回滚)
*/
🎯 实现原理
源码分析
/**
* ApplicationEventPublisher:事件发布器接口
*/
@FunctionalInterface
public interface ApplicationEventPublisher {
/**
* 发布事件
*/
void publishEvent(Object event);
}
/**
* ApplicationContext实现了ApplicationEventPublisher
*/
public abstract class AbstractApplicationContext extends DefaultResourceLoader
implements ConfigurableApplicationContext {
/**
* 事件多播器
*/
private ApplicationEventMulticaster applicationEventMulticaster;
/**
* 发布事件
*/
@Override
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, ResolvableType eventType) {
// 1. 包装事件
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) {
applicationEvent = (ApplicationEvent) event;
} else {
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// 2. 多播事件
if (this.applicationEventMulticaster != null) {
this.applicationEventMulticaster.multicastEvent(applicationEvent, eventType);
}
// 3. 发布到父容器
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
}
}
/**
* ApplicationEventMulticaster:事件多播器
*/
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
/**
* 多播事件
*/
@Override
public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
// 获取所有监听器
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
// 异步执行
executor.execute(() -> invokeListener(listener, event));
} else {
// 同步执行
invokeListener(listener, event);
}
}
}
/**
* 调用监听器
*/
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
} catch (Throwable err) {
errorHandler.handleError(err);
}
} else {
doInvokeListener(listener, event);
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
} catch (ClassCastException ex) {
// 类型不匹配,忽略
}
}
}
💻 实战案例
案例1:用户注册完整流程
/**
* 用户注册事件
*/
public class UserRegisterEvent extends ApplicationEvent {
private User user;
public UserRegisterEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
/**
* 用户服务:发布事件
*/
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private UserMapper userMapper;
/**
* 用户注册
*/
@Transactional
public void register(RegisterRequest request) {
// 1. 保存用户
User user = new User();
user.setUsername(request.getUsername());
user.setEmail(request.getEmail());
user.setPhone(request.getPhone());
user.setCreateTime(new Date());
userMapper.insert(user);
// 2. 发布事件
eventPublisher.publishEvent(new UserRegisterEvent(this, user));
System.out.println("用户注册完成");
}
}
/**
* 邮件监听器
*/
@Component
public class EmailListener {
@Autowired
private EmailService emailService;
@Async
@EventListener
@Order(1)
public void handleUserRegister(UserRegisterEvent event) {
User user = event.getUser();
System.out.println("发送欢迎邮件:" + user.getEmail());
// 发送邮件
emailService.sendWelcomeEmail(
user.getEmail(),
"欢迎注册",
"欢迎您," + user.getUsername() + "!"
);
}
}
/**
* 短信监听器
*/
@Component
public class SmsListener {
@Autowired
private SmsService smsService;
@Async
@EventListener
@Order(2)
public void handleUserRegister(UserRegisterEvent event) {
User user = event.getUser();
System.out.println("发送欢迎短信:" + user.getPhone());
// 发送短信
smsService.sendWelcomeSms(
user.getPhone(),
"欢迎注册!"
);
}
}
/**
* 积分监听器
*/
@Component
public class PointListener {
@Autowired
private PointService pointService;
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
@Order(3)
public void handleUserRegister(UserRegisterEvent event) {
User user = event.getUser();
System.out.println("赠送注册积分");
// 赠送积分
pointService.givePoints(user.getId(), 100, "注册奖励");
}
}
/**
* 日志监听器
*/
@Component
public class LogListener {
@Autowired
private LogService logService;
@Async
@EventListener
@Order(4)
public void handleUserRegister(UserRegisterEvent event) {
User user = event.getUser();
System.out.println("记录操作日志");
// 记录日志
logService.log("用户注册", "userId=" + user.getId());
}
}
案例2:订单状态变更
/**
* 订单状态变更事件
*/
public class OrderStatusChangedEvent extends ApplicationEvent {
private Order order;
private OrderStatus oldStatus;
private OrderStatus newStatus;
public OrderStatusChangedEvent(Object source, Order order,
OrderStatus oldStatus, OrderStatus newStatus) {
super(source);
this.order = order;
this.oldStatus = oldStatus;
this.newStatus = newStatus;
}
// getter...
}
/**
* 订单服务
*/
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
/**
* 更新订单状态
*/
@Transactional
public void updateStatus(Long orderId, OrderStatus newStatus) {
// 1. 查询订单
Order order = orderMapper.selectById(orderId);
OrderStatus oldStatus = order.getStatus();
// 2. 更新状态
order.setStatus(newStatus);
orderMapper.updateById(order);
// 3. 发布事件
eventPublisher.publishEvent(
new OrderStatusChangedEvent(this, order, oldStatus, newStatus)
);
}
}
/**
* 订单状态监听器
*/
@Component
public class OrderStatusListener {
/**
* 订单支付成功
*/
@EventListener(condition = "#event.newStatus.name() == 'PAID'")
public void handleOrderPaid(OrderStatusChangedEvent event) {
Order order = event.getOrder();
System.out.println("订单支付成功:" + order.getOrderNo());
// 减库存、发货等
}
/**
* 订单已发货
*/
@EventListener(condition = "#event.newStatus.name() == 'SHIPPED'")
public void handleOrderShipped(OrderStatusChangedEvent event) {
Order order = event.getOrder();
System.out.println("订单已发货:" + order.getOrderNo());
// 发送物流通知
}
/**
* 订单已完成
*/
@EventListener(condition = "#event.newStatus.name() == 'COMPLETED'")
public void handleOrderCompleted(OrderStatusChangedEvent event) {
Order order = event.getOrder();
System.out.println("订单已完成:" + order.getOrderNo());
// 增加积分、评价提醒等
}
}
🎉 总结
核心要点
1. 事件驱动
- 发布-订阅模式
- 解耦
2. 三个核心
- ApplicationEvent:事件
- ApplicationEventPublisher:发布器
- ApplicationListener:监听器
3. 高级特性
- 条件监听
- 异步监听
- 事务监听
- 执行顺序
4. 使用场景
- 用户注册
- 订单处理
- 日志记录
- 统计分析
最佳实践
1. 事件命名
- XxxEvent
- 明确语义
2. 监听器命名
- XxxListener
- 单一职责
3. 异步处理
- 耗时操作使用@Async
- 不阻塞主流程
4. 事务处理
- 使用@TransactionalEventListener
- 在正确的阶段执行
5. 异常处理
- 监听器中捕获异常
- 不影响其他监听器
记忆口诀
Spring事件机制好,
观察者模式巧妙。
三个核心要记牢:
ApplicationEvent事件,
ApplicationEventPublisher发布器,
ApplicationListener监听器。
发布事件很简单,
publishEvent方法调。
监听事件两方式,
接口实现或注解。
@EventListener注解用,
方法参数是事件。
condition条件过滤,
精准监听更高效。
@Async异步执行,
耗时操作不阻塞。
@Order指定顺序,
监听器按序执行。
@TransactionalEventListener特殊,
事务阶段来执行。
AFTER_COMMIT提交后,
AFTER_ROLLBACK回滚后。
事件驱动解耦好,
扩展维护都方便。
用户注册和订单,
事件机制来实现!
愿你的组件间通信优雅解耦,事件驱动设计精妙! 📡✨