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 事件监听方式
- 实现 ApplicationListener 接口
- @EventListener 注解
- @TransactionalEventListener 注解
2.5 异步事件
默认情况下,Spring 事件是同步执行的。要实现异步事件:
- @Async + @EventListener
- 自定义 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);
}
// 可以执行额外的操作,如通知其他节点
}
}
五、总结与最佳实践
最佳实践
-
事件设计
- 事件类名以 Event 结尾
- 包含必要的业务数据
- 避免包含大对象
-
事件发布
- 在业务逻辑完成后发布
- 考虑事务边界
- 避免循环发布
-
事件监听
- 优先使用 @EventListener
- 异步处理耗时操作
- 处理好异常
-
事务事件
- 使用 @TransactionalEventListener
- 选择合适的 phase
- 确保幂等性
注意事项
-
同步 vs 异步
- 同步:保证顺序,但有性能影响
- 异步:提高性能,但可能丢失事件
-
异常处理
- 监听器异常不会影响发布者
- 异步监听器需要自行处理异常
-
循环依赖
- 避免事件循环发布
- 监听器不要再发布同类事件
Spring 事件机制是实现业务解耦的强大工具,合理使用事件驱动模式,能够使系统更加灵活、可维护。理解事件的生命周期和传播机制,选择合适的监听方式,是使用好这一机制的关键。