观察者模式与Spring事件引言观察者模式是经典的行为型设计模式Spring Framework通过ApplicationEvent机制实现了这一模式。Spring事件系统允许组件之间进行松耦合通信一个组件发布事件其他组件可以独立地响应这些事件。本文将详细介绍Spring事件机制、事件发布订阅、异步处理以及在Spring Boot中的应用。一、Spring事件机制1.1 核心组件Spring事件机制包含三个核心组件ApplicationEvent是所有事件的基类ApplicationListener是事件监听器接口ApplicationEventPublisher是事件发布器。// 1. 定义事件 public class OrderCreatedEvent extends ApplicationEvent { private final Order order; private final LocalDateTime timestamp; public OrderCreatedEvent(Object source, Order order) { super(source); this.order order; this.timestamp LocalDateTime.now(); } public Order getOrder() { return order; } public LocalDateTime getTimestamp() { return timestamp; } } // 2. 定义监听器 Component public class OrderEventListener { private final OrderService orderService; public OrderEventListener(OrderService orderService) { this.orderService orderService; } EventListener public void handleOrderCreated(OrderCreatedEvent event) { Order order event.getOrder(); orderService.processOrderCreation(order); } } // 3. 发布事件 Service public class OrderService { private final ApplicationEventPublisher publisher; public OrderService(ApplicationEventPublisher publisher) { this.publisher publisher; } public Order createOrder(Order order) { Order saved orderRepository.save(order); // 发布事件 publisher.publishEvent(new OrderCreatedEvent(this, saved)); return saved; } }2.1 监听器排序Component Order(1) public class FirstListener { EventListener public void handle(Event event) { System.out.println(First listener); } } Component Order(2) public class SecondListener { EventListener public void handle(Event event) { System.out.println(Second listener); } }2.2 Async异步处理Service public class NotificationService { Async EventListener Order(10) public void handleOrderCreated(OrderCreatedEvent event) { // 异步发送通知不阻塞主流程 sendEmailNotification(event.getOrder()); sendSmsNotification(event.getOrder()); } }2.3 条件监听Component public class ConditionalListener { EventListener( condition #event.order.amount 1000 ) public void handleHighValueOrder(OrderCreatedEvent event) { // 只处理金额大于1000的订单 processHighValueOrder(event.getOrder()); } }三、事务事件3.1 事务同步器Service public class TransactionalEventListener { TransactionalEventListener( phase TransactionPhase.BEFORE_COMMIT ) public void beforeCommit(OrderCreatedEvent event) { // 事务提交前执行 } TransactionalEventListener( phase TransactionPhase.AFTER_COMMIT ) public void afterCommit(OrderCreatedEvent event) { // 事务提交后执行 } TransactionalEventListener( phase TransactionPhase.AFTER_ROLLBACK ) public void afterRollback(OrderCreatedEvent event) { // 事务回滚后执行 } TransactionalEventListener( phase TransactionPhase.AFTER_COMPLETION ) public void afterCompletion(OrderCreatedEvent event) { // 事务完成后执行无论提交还是回滚 } }3.2 事件顺序保证Configuration public class EventConfig { Bean public ApplicationEventMulticaster applicationEventMulticaster( ConfigurableBeanFactory beanFactory) { SimpleApplicationEventMulticaster multicaster new SimpleApplicationEventMulticaster(beanFactory); multicaster.setTaskExecutor( new SyncTaskExecutor()); // 使用同步执行器保证顺序 return multicaster; } }四、自定义事件系统4.1 事件总线Component public class DomainEventBus { private final ApplicationEventPublisher publisher; private final MapString, ListEventListener? listeners new ConcurrentHashMap(); public DomainEventBus(ApplicationEventPublisher publisher) { this.publisher publisher; } public void publish(DomainEvent event) { publisher.publishEvent(event); // 本地监听 String eventType event.getClass().getSimpleName(); ListEventListener? listeners this.listeners.get(eventType); if (listeners ! null) { listeners.forEach(l - l.onEvent(event)); } } public T extends DomainEvent void subscribe( ClassT eventType, ConsumerT handler) { listeners.computeIfAbsent( eventType.getSimpleName(), k - new CopyOnWriteArrayList() ).add(new SimpleEventListener(handler)); } private static class SimpleEventListenerT implements EventListener { private final ConsumerT handler; public SimpleEventListener(ConsumerT handler) { this.handler handler; } SuppressWarnings(unchecked) Override public void onEvent(Object event) { handler.accept((T) event); } } }4.2 事件溯源public interface DomainEvent { String getEventId(); String getAggregateId(); LocalDateTime getOccurredOn(); } public class OrderCreated implements DomainEvent { private final String eventId UUID.randomUUID().toString(); private final String orderId; private final BigDecimal amount; private final LocalDateTime occurredOn LocalDateTime.now(); public OrderCreated(String orderId, BigDecimal amount) { this.orderId orderId; this.amount amount; } Override public String getEventId() { return eventId; } Override public String getAggregateId() { return orderId; } Override public LocalDateTime getOccurredOn() { return occurredOn; } } Service public class EventStoreService { private final ListDomainEvent eventStore new ArrayList(); public void save(DomainEvent event) { eventStore.add(event); } public ListDomainEvent getEvents(String aggregateId) { return eventStore.stream() .filter(e - e.getAggregateId().equals(aggregateId)) .collect(Collectors.toList()); } }五、Spring Security事件5.1 认证事件Component public class SecurityEventListener { private final AuditService auditService; public SecurityEventListener(AuditService auditService) { this.auditService auditService; } EventListener public void handleAuthenticationSuccess( AuthenticationSuccessEvent event) { Authentication auth event.getAuthentication(); auditService.log(LOGIN_SUCCESS, auth.getName(), auth.getDetails()); } EventListener public void handleAuthenticationFailure( AuthenticationFailureBadCredentialsEvent event) { AuthenticationException auth event.getException(); auditService.log(LOGIN_FAILURE, event.getAuthentication().getName(), auth.getMessage()); } EventListener public void handleLogoutSuccess( LogoutSuccessEvent event) { Authentication auth event.getAuthentication(); auditService.log(LOGOUT, auth.getName(), null); } }5.2 访问事件Component public class AccessEventListener { EventListener public void handleAccessDenied(AccessDeniedEvent event) { SecurityUser user (SecurityUser) event.getAuthentication() .getPrincipal(); String resource event.getSource().toString(); accessLogService.logDeniedAccess( user.getId(), resource); } }六、最佳实践6.1 事件设计原则// 好的实践不可变事件 public class OrderEvent { private final String eventId; private final Order order; private final LocalDateTime timestamp; public OrderEvent(Order order) { this.eventId UUID.randomUUID().toString(); this.order order; this.timestamp LocalDateTime.now(); } // 只有getter public String getEventId() { return eventId; } public Order getOrder() { return order; } public LocalDateTime getTimestamp() { return timestamp; } }6.2 异常处理Async EventListener public void handleEvent(ErrorHandlingEvent event) { try { doProcess(event); } catch (Exception e) { handleException(event, e); } } Async EventListener( errorHandler customErrorHandler ) public void handleEventWithErrorHandler(Event event) { // 异常由errorHandler处理 }6.3 性能优化Configuration public class AsyncEventConfig { Bean public Executor eventExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); executor.setThreadNamePrefix(async-event-); executor.initialize(); return executor; } } Service public class AsyncEventPublisher { private final ApplicationEventPublisher publisher; private final Executor executor; public AsyncEventPublisher( ApplicationEventPublisher publisher, Qualifier(eventExecutor) Executor executor) { this.publisher publisher; this.executor executor; } public void publishEventAsync(ApplicationEvent event) { executor.execute(() - publisher.publishEvent(event)); } }总结Spring事件系统提供了优雅的组件间通信机制通过事件驱动可以实现业务逻辑的解耦。合理使用Spring事件需要注意事件的设计规范、事务边界处理、异步性能优化等问题。对于复杂场景可以构建自定义事件总线支持更多的发布订阅模式。
观察者模式与Spring事件
观察者模式与Spring事件引言观察者模式是经典的行为型设计模式Spring Framework通过ApplicationEvent机制实现了这一模式。Spring事件系统允许组件之间进行松耦合通信一个组件发布事件其他组件可以独立地响应这些事件。本文将详细介绍Spring事件机制、事件发布订阅、异步处理以及在Spring Boot中的应用。一、Spring事件机制1.1 核心组件Spring事件机制包含三个核心组件ApplicationEvent是所有事件的基类ApplicationListener是事件监听器接口ApplicationEventPublisher是事件发布器。// 1. 定义事件 public class OrderCreatedEvent extends ApplicationEvent { private final Order order; private final LocalDateTime timestamp; public OrderCreatedEvent(Object source, Order order) { super(source); this.order order; this.timestamp LocalDateTime.now(); } public Order getOrder() { return order; } public LocalDateTime getTimestamp() { return timestamp; } } // 2. 定义监听器 Component public class OrderEventListener { private final OrderService orderService; public OrderEventListener(OrderService orderService) { this.orderService orderService; } EventListener public void handleOrderCreated(OrderCreatedEvent event) { Order order event.getOrder(); orderService.processOrderCreation(order); } } // 3. 发布事件 Service public class OrderService { private final ApplicationEventPublisher publisher; public OrderService(ApplicationEventPublisher publisher) { this.publisher publisher; } public Order createOrder(Order order) { Order saved orderRepository.save(order); // 发布事件 publisher.publishEvent(new OrderCreatedEvent(this, saved)); return saved; } }2.1 监听器排序Component Order(1) public class FirstListener { EventListener public void handle(Event event) { System.out.println(First listener); } } Component Order(2) public class SecondListener { EventListener public void handle(Event event) { System.out.println(Second listener); } }2.2 Async异步处理Service public class NotificationService { Async EventListener Order(10) public void handleOrderCreated(OrderCreatedEvent event) { // 异步发送通知不阻塞主流程 sendEmailNotification(event.getOrder()); sendSmsNotification(event.getOrder()); } }2.3 条件监听Component public class ConditionalListener { EventListener( condition #event.order.amount 1000 ) public void handleHighValueOrder(OrderCreatedEvent event) { // 只处理金额大于1000的订单 processHighValueOrder(event.getOrder()); } }三、事务事件3.1 事务同步器Service public class TransactionalEventListener { TransactionalEventListener( phase TransactionPhase.BEFORE_COMMIT ) public void beforeCommit(OrderCreatedEvent event) { // 事务提交前执行 } TransactionalEventListener( phase TransactionPhase.AFTER_COMMIT ) public void afterCommit(OrderCreatedEvent event) { // 事务提交后执行 } TransactionalEventListener( phase TransactionPhase.AFTER_ROLLBACK ) public void afterRollback(OrderCreatedEvent event) { // 事务回滚后执行 } TransactionalEventListener( phase TransactionPhase.AFTER_COMPLETION ) public void afterCompletion(OrderCreatedEvent event) { // 事务完成后执行无论提交还是回滚 } }3.2 事件顺序保证Configuration public class EventConfig { Bean public ApplicationEventMulticaster applicationEventMulticaster( ConfigurableBeanFactory beanFactory) { SimpleApplicationEventMulticaster multicaster new SimpleApplicationEventMulticaster(beanFactory); multicaster.setTaskExecutor( new SyncTaskExecutor()); // 使用同步执行器保证顺序 return multicaster; } }四、自定义事件系统4.1 事件总线Component public class DomainEventBus { private final ApplicationEventPublisher publisher; private final MapString, ListEventListener? listeners new ConcurrentHashMap(); public DomainEventBus(ApplicationEventPublisher publisher) { this.publisher publisher; } public void publish(DomainEvent event) { publisher.publishEvent(event); // 本地监听 String eventType event.getClass().getSimpleName(); ListEventListener? listeners this.listeners.get(eventType); if (listeners ! null) { listeners.forEach(l - l.onEvent(event)); } } public T extends DomainEvent void subscribe( ClassT eventType, ConsumerT handler) { listeners.computeIfAbsent( eventType.getSimpleName(), k - new CopyOnWriteArrayList() ).add(new SimpleEventListener(handler)); } private static class SimpleEventListenerT implements EventListener { private final ConsumerT handler; public SimpleEventListener(ConsumerT handler) { this.handler handler; } SuppressWarnings(unchecked) Override public void onEvent(Object event) { handler.accept((T) event); } } }4.2 事件溯源public interface DomainEvent { String getEventId(); String getAggregateId(); LocalDateTime getOccurredOn(); } public class OrderCreated implements DomainEvent { private final String eventId UUID.randomUUID().toString(); private final String orderId; private final BigDecimal amount; private final LocalDateTime occurredOn LocalDateTime.now(); public OrderCreated(String orderId, BigDecimal amount) { this.orderId orderId; this.amount amount; } Override public String getEventId() { return eventId; } Override public String getAggregateId() { return orderId; } Override public LocalDateTime getOccurredOn() { return occurredOn; } } Service public class EventStoreService { private final ListDomainEvent eventStore new ArrayList(); public void save(DomainEvent event) { eventStore.add(event); } public ListDomainEvent getEvents(String aggregateId) { return eventStore.stream() .filter(e - e.getAggregateId().equals(aggregateId)) .collect(Collectors.toList()); } }五、Spring Security事件5.1 认证事件Component public class SecurityEventListener { private final AuditService auditService; public SecurityEventListener(AuditService auditService) { this.auditService auditService; } EventListener public void handleAuthenticationSuccess( AuthenticationSuccessEvent event) { Authentication auth event.getAuthentication(); auditService.log(LOGIN_SUCCESS, auth.getName(), auth.getDetails()); } EventListener public void handleAuthenticationFailure( AuthenticationFailureBadCredentialsEvent event) { AuthenticationException auth event.getException(); auditService.log(LOGIN_FAILURE, event.getAuthentication().getName(), auth.getMessage()); } EventListener public void handleLogoutSuccess( LogoutSuccessEvent event) { Authentication auth event.getAuthentication(); auditService.log(LOGOUT, auth.getName(), null); } }5.2 访问事件Component public class AccessEventListener { EventListener public void handleAccessDenied(AccessDeniedEvent event) { SecurityUser user (SecurityUser) event.getAuthentication() .getPrincipal(); String resource event.getSource().toString(); accessLogService.logDeniedAccess( user.getId(), resource); } }六、最佳实践6.1 事件设计原则// 好的实践不可变事件 public class OrderEvent { private final String eventId; private final Order order; private final LocalDateTime timestamp; public OrderEvent(Order order) { this.eventId UUID.randomUUID().toString(); this.order order; this.timestamp LocalDateTime.now(); } // 只有getter public String getEventId() { return eventId; } public Order getOrder() { return order; } public LocalDateTime getTimestamp() { return timestamp; } }6.2 异常处理Async EventListener public void handleEvent(ErrorHandlingEvent event) { try { doProcess(event); } catch (Exception e) { handleException(event, e); } } Async EventListener( errorHandler customErrorHandler ) public void handleEventWithErrorHandler(Event event) { // 异常由errorHandler处理 }6.3 性能优化Configuration public class AsyncEventConfig { Bean public Executor eventExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); executor.setThreadNamePrefix(async-event-); executor.initialize(); return executor; } } Service public class AsyncEventPublisher { private final ApplicationEventPublisher publisher; private final Executor executor; public AsyncEventPublisher( ApplicationEventPublisher publisher, Qualifier(eventExecutor) Executor executor) { this.publisher publisher; this.executor executor; } public void publishEventAsync(ApplicationEvent event) { executor.execute(() - publisher.publishEvent(event)); } }总结Spring事件系统提供了优雅的组件间通信机制通过事件驱动可以实现业务逻辑的解耦。合理使用Spring事件需要注意事件的设计规范、事务边界处理、异步性能优化等问题。对于复杂场景可以构建自定义事件总线支持更多的发布订阅模式。