Spring Event 企业级应用

Spring 框架提供的事件驱动编程模型,基于观察者模式实现。它允许应用程序的不同组件之间进行松耦合的通信,当一个组件发布事件时,其他监听该事件的组件可以异步或同步地做出响应。

电商项目中的使用

①、定义事件

  • BaseEvent 基础事件抽象类
  • UserRegisteredEvent extends BaseEvent 用户注册事件
  • OrderCreatedEvent extends BaseEvent 订单创建事件
  • PaymentSuccessEvent extends BaseEvent 支付成功事件
  • InventoryDeductedEvent extends BaseEvent 库存扣减事件
  • SystemAlertEvent extends BaseEvent 系统告警事件
java 复制代码
public abstract class BaseEvent{
	
	protected String eventId;
	protected LocalDateTime timestamp;
	protected String source;

	public BaseEvent(String source){
		this.eventId = UUID.randomUUID().toString();
		this.timestamp = LocalDateTime.now();
		this.source = source;
	}

	//getter...
}
java 复制代码
// 用户注册事件
public class UserRegisteredEvent extends BaseEvent {
    private Long userId;
    private String username;
    private String email;
    private String phone;

    public UserRegisteredEvent(String source, Long userId, String username, String email, String phone) {
        super(source);
        this.userId = userId;
        this.username = username;
        this.email = email;
        this.phone = phone;
    }
    // getters...
}
java 复制代码
// 订单创建事件
public class OrderCreatedEvent extends BaseEvent {
    private Long orderId;
    private Long userId;
    private BigDecimal amount;
    private List<OrderItem> items;

    public OrderCreatedEvent(String source, Long orderId, Long userId, BigDecimal amount, List<OrderItem> items) {
        super(source);
        this.orderId = orderId;
        this.userId = userId;
        this.amount = amount;
        this.items = items;
    }
    // getters...
}
java 复制代码
// 支付成功事件
public class PaymentSuccessEvent extends BaseEvent {
    private Long paymentId;
    private Long orderId;
    private BigDecimal amount;
    private String paymentMethod;

    public PaymentSuccessEvent(String source, Long paymentId, Long orderId, BigDecimal amount, String paymentMethod) {
        super(source);
        this.paymentId = paymentId;
        this.orderId = orderId;
        this.amount = amount;
        this.paymentMethod = paymentMethod;
    }
    // getters...
}
java 复制代码
// 库存扣减事件
public class InventoryDeductedEvent extends BaseEvent {
    private Long orderId;
    private List<InventoryItem> deductedItems;

    public InventoryDeductedEvent(String source, Long orderId, List<InventoryItem> deductedItems) {
        super(source);
        this.orderId = orderId;
        this.deductedItems = deductedItems;
    }
    // getters...
}
java 复制代码
// 系统告警事件
public class SystemAlertEvent extends BaseEvent {
    private AlertLevel level;
    private String module;
    private String message;
    private Map<String, Object> context;

    public SystemAlertEvent(String source, AlertLevel level, String module, String message, Map<String, Object> context) {
        super(source);
        this.level = level;
        this.module = module;
        this.message = message;
        this.context = context;
    }
    // getters...
}


public enum AlertLevel {
    INFO, WARNING, ERROR, CRITICAL
}

②、事件监听器

  • EmailNotificationListener 邮件通知监听器
  • SmsNotificationListener SMS通知监听器
  • PointsEventListener 积分处理监听器
  • InventoryEventListener 库存管理监听器
  • AnalyticsEventListener 数据分析监听器
  • MonitoringEventListener 统监控监听器
  • AuditLogEventListener 审计日志监听器
java 复制代码
@Component
@Slf4j
public class EmailNotifactionListener{
	
	@Async("emailTaskExecutor")
	@EventListener
	@Order(1) //执行顺序
	public void handleUserRegistered(UserRegisteredEvent event){
		try {
            log.info("发送欢迎邮件给用户: {}", event.getEmail());
            // 模拟邮件发送
            Thread.sleep(100);
            log.info("欢迎邮件发送成功: {}", event.getEmail());
        } catch (Exception e) {
            log.error("发送欢迎邮件失败", e);
        }
	}

	@Async("emailTaskExecutor")
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) {
        log.info("发送订单确认邮件, 订单ID: {}", event.getOrderId());
        // 实际邮件发送逻辑...
    }

    @Async("emailTaskExecutor")
    @EventListener
    public void handlePaymentSuccess(PaymentSuccessEvent event) {
        log.info("发送支付成功邮件, 订单ID: {}", event.getOrderId());
        // 实际邮件发送逻辑...
    }
}
java 复制代码
// SMS通知监听器
@Component
@Slf4j
public class SmsNotificationListener {
    
    @Async("smsTaskExecutor")
    @EventListener
    public void handleUserRegistered(UserRegisteredEvent event) {
        if (StringUtils.isNotBlank(event.getPhone())) {
            log.info("发送欢迎短信到: {}", event.getPhone());
            // 实际短信发送逻辑...
        }
    }

    @Async("smsTaskExecutor")
    @EventListener
    public void handlePaymentSuccess(PaymentSuccessEvent event) {
        log.info("发送支付成功短信, 订单ID: {}", event.getOrderId());
        // 实际短信发送逻辑...
    }
}
java 复制代码
// 积分处理监听器
@Component
@Slf4j
public class PointsEventListener {
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleUserRegistration(UserRegisteredEvent event) {
        log.info("为新用户赠送积分, 用户ID: {}", event.getUserId());
        // 积分服务调用...
    }

    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleOrderPayment(PaymentSuccessEvent event) {
        log.info("为订单支付增加积分, 订单ID: {}", event.getOrderId());
        // 根据订单金额计算积分...
    }
}
java 复制代码
// 库存管理监听器
@Component
@Slf4j
public class InventoryEventListener {
    
    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
    public void handleOrderCreated(OrderCreatedEvent event) {
        log.info("预扣减库存, 订单ID: {}", event.getOrderId());
        // 库存预扣减逻辑...
        // 发布库存扣减事件
        ApplicationEventPublisher eventPublisher = ...;
        eventPublisher.publishEvent(new InventoryDeductedEvent(
            "InventoryService", 
            event.getOrderId(), 
            deductedItems
        ));
    }

    @EventListener
    public void handleInventoryDeducted(InventoryDeductedEvent event) {
        log.info("库存扣减完成, 订单ID: {}", event.getOrderId());
        // 更新库存状态...
    }
}
java 复制代码
// 数据分析监听器
@Component
@Slf4j
public class AnalyticsEventListener {
    
    @Async("analyticsTaskExecutor")
    @EventListener
    public void handleUserBehavior(BaseEvent event) {
        log.info("记录用户行为事件到数据分析系统: {}", event.getClass().getSimpleName());
        // 发送到Kafka或写入数据仓库...
    }
}
java 复制代码
// 系统监控监听器
@Component
@Slf4j
public class MonitoringEventListener {
    
    @EventListener
    public void handleSystemAlert(SystemAlertEvent event) {
        switch (event.getLevel()) {
            case ERROR:
            case CRITICAL:
                log.error("系统告警: {} - {} - {}", event.getModule(), event.getMessage(), event.getContext());
                // 发送到监控平台...
                break;
            case WARNING:
                log.warn("系统警告: {} - {}", event.getModule(), event.getMessage());
                break;
            case INFO:
                log.info("系统信息: {} - {}", event.getModule(), event.getMessage());
                break;
        }
    }
}
java 复制代码
// 审计日志监听器
@Component
@Slf4j
public class AuditLogEventListener {
    
    @EventListener
    public void handleAllEvents(BaseEvent event) {
        log.info("审计日志 - 事件类型: {}, 事件ID: {}, 时间: {}", 
                event.getClass().getSimpleName(), 
                event.getEventId(), 
                event.getTimestamp());
        
        // 写入审计数据库
        auditLogService.save(new AuditLog(
            event.getEventId(),
            event.getClass().getSimpleName(),
            event.getSource(),
            event.getTimestamp(),
            event
        ));
    }
}

③、事件发布服务

java 复制代码
@Service
@Slf4j
public class EventPublisherService {
    
    private final ApplicationEventPublisher eventPublisher;
    private final MeterRegistry meterRegistry;

    public EventPublisherService(ApplicationEventPublisher eventPublisher, 
                               MeterRegistry meterRegistry) {
        this.eventPublisher = eventPublisher;
        this.meterRegistry = meterRegistry;
    }

    public void publishUserRegistered(Long userId, String username, String email, String phone) {
        UserRegisteredEvent event = new UserRegisteredEvent(
            "UserService", userId, username, email, phone
        );
        publishEvent(event);
    }

    public void publishOrderCreated(Long orderId, Long userId, BigDecimal amount, List<OrderItem> items) {
        OrderCreatedEvent event = new OrderCreatedEvent(
            "OrderService", orderId, userId, amount, items
        );
        publishEvent(event);
    }

    public void publishPaymentSuccess(Long paymentId, Long orderId, BigDecimal amount, String paymentMethod) {
        PaymentSuccessEvent event = new PaymentSuccessEvent(
            "PaymentService", paymentId, orderId, amount, paymentMethod
        );
        publishEvent(event);
    }

    public void publishSystemAlert(AlertLevel level, String module, String message, Map<String, Object> context) {
        SystemAlertEvent event = new SystemAlertEvent(
            module, level, module, message, context
        );
        publishEvent(event);
    }

    private void publishEvent(BaseEvent event) {
        try {
            eventPublisher.publishEvent(event);
            meterRegistry.counter("event.published", "type", event.getClass().getSimpleName())
                        .increment();
            log.debug("事件发布成功: {}", event.getEventId());
        } catch (Exception e) {
            log.error("事件发布失败: {}", event.getEventId(), e);
            meterRegistry.counter("event.publish.failed", "type", event.getClass().getSimpleName())
                        .increment();
        }
    }
}

④、配置类

java 复制代码
@Configuration
@EnableAsync
@EnableScheduling
public class EventConfig {
    
    // 邮件任务线程池
    @Bean("emailTaskExecutor")
    public TaskExecutor emailTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("email-exec-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    // SMS任务线程池
    @Bean("smsTaskExecutor")
    public TaskExecutor smsTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(5);
        executor.setQueueCapacity(50);
        executor.setThreadNamePrefix("sms-exec-");
        executor.initialize();
        return executor;
    }

    // 数据分析任务线程池
    @Bean("analyticsTaskExecutor")
    public TaskExecutor analyticsTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(1000);
        executor.setThreadNamePrefix("analytics-exec-");
        executor.initialize();
        return executor;
    }
}
java 复制代码
// 事件监控配置
@Configuration
public class EventMonitoringConfig {
    
    @Bean
    public MeterRegistryCustomizer<MeterRegistry> eventMetrics() {
        return registry -> {
            // 事件发布统计
            Counter.builder("event.published")
                  .description("已发布事件数量")
                  .tag("type", "all")
                  .register(registry);
            
            // 事件处理时间统计
            Timer.builder("event.processing.time")
                .description("事件处理时间")
                .register(registry);
        };
    }
}

⑤、业务服务中使用

java 复制代码
@Service
@Slf4j
public class UserService {
    
    private final UserRepository userRepository;
    private final EventPublisherService eventPublisher;

    public UserService(UserRepository userRepository, EventPublisherService eventPublisher) {
        this.userRepository = userRepository;
        this.eventPublisher = eventPublisher;
    }

    @Transactional
    public User registerUser(UserRegistrationRequest request) {
        // 验证业务逻辑...
        
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        
        User savedUser = userRepository.save(user);
        
        // 发布用户注册事件
        eventPublisher.publishUserRegistered(
            savedUser.getId(),
            savedUser.getUsername(),
            savedUser.getEmail(),
            savedUser.getPhone()
        );
        
        return savedUser;
    }
}

@Service
@Slf4j
public class OrderService {
    
    private final OrderRepository orderRepository;
    private final EventPublisherService eventPublisher;

    public OrderService(OrderRepository orderRepository, EventPublisherService eventPublisher) {
        this.orderRepository = orderRepository;
        this.eventPublisher = eventPublisher;
    }

    @Transactional
    public Order createOrder(OrderCreateRequest request) {
        // 创建订单逻辑...
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setAmount(calculateAmount(request.getItems()));
        order.setItems(request.getItems());
        
        Order savedOrder = orderRepository.save(order);
        
        // 发布订单创建事件
        eventPublisher.publishOrderCreated(
            savedOrder.getId(),
            savedOrder.getUserId(),
            savedOrder.getAmount(),
            savedOrder.getItems()
        );
        
        return savedOrder;
    }
}
java 复制代码
@Service
@Slf4j
public class PaymentService {
    
    private final PaymentRepository paymentRepository;
    private final EventPublisherService eventPublisher;

    public PaymentService(PaymentRepository paymentRepository, EventPublisherService eventPublisher) {
        this.paymentRepository = paymentRepository;
        this.eventPublisher = eventPublisher;
    }

    @Transactional
    public Payment processPayment(PaymentRequest request) {
        // 支付处理逻辑...
        Payment payment = new Payment();
        payment.setOrderId(request.getOrderId());
        payment.setAmount(request.getAmount());
        payment.setPaymentMethod(request.getPaymentMethod());
        payment.setStatus(PaymentStatus.SUCCESS);
        
        Payment savedPayment = paymentRepository.save(payment);
        
        // 发布支付成功事件
        eventPublisher.publishPaymentSuccess(
            savedPayment.getId(),
            savedPayment.getOrderId(),
            savedPayment.getAmount(),
            savedPayment.getPaymentMethod()
        );
        
        return savedPayment;
    }
}

⑥、监控和健康检查

java 复制代码
@Component
@Slf4j
public class EventHealthIndicator implements HealthIndicator {
    
    private final MeterRegistry meterRegistry;

    public EventHealthIndicator(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Override
    public Health health() {
        double failedEvents = meterRegistry.counter("event.publish.failed", "type", "all").count();
        double totalEvents = meterRegistry.counter("event.published", "type", "all").count();
        
        double failureRate = totalEvents > 0 ? failedEvents / totalEvents : 0;
        
        Health.Builder builder = failureRate > 0.1 ? Health.down() : Health.up();
        
        return builder
            .withDetail("total_events", totalEvents)
            .withDetail("failed_events", failedEvents)
            .withDetail("failure_rate", String.format("%.2f%%", failureRate * 100))
            .build();
    }
}
java 复制代码
// 事件统计端点
@RestController
@RequestMapping("/admin/events")
public class EventStatisticsController {
    
    private final MeterRegistry meterRegistry;

    public EventStatisticsController(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @GetMapping("/statistics")
    public Map<String, Object> getEventStatistics() {
        Map<String, Object> stats = new HashMap<>();
        
        // 获取各种事件类型的统计
        meterRegistry.find("event.published").counters().forEach(counter -> {
            String type = counter.getId().getTag("type");
            stats.put("published_" + type, counter.count());
        });
        
        meterRegistry.find("event.publish.failed").counters().forEach(counter -> {
            String type = counter.getId().getTag("type");
            stats.put("failed_" + type, counter.count());
        });
        
        return stats;
    }
}
相关推荐
代码雕刻家5 分钟前
编程语法细节
java·c语言·开发语言
SimonKing8 分钟前
Agnes AI出桌面版了,可图可视频,免费用
java·后端·程序员
左左右右左右摇晃27 分钟前
手写Tomcat原理整理
java·开发语言·笔记·tomcat
孫治AllenSun31 分钟前
【JVM】四大引用类型分析
java·开发语言·jvm
于慨33 分钟前
安装java
java
夕除34 分钟前
sign 是什么
java·前端
Penina10181 小时前
代码如何导入idea
java·intellij idea
.Hypocritical.1 小时前
Maven笔记——2
java·笔记·maven
huohuopro1 小时前
手写 Tomcat 步骤教程
java·网络
snow@li1 小时前
Java:Lombok 完整讲解
java