Spring Boot 事件发布与监听 观察者模式的实际应用 - 实践

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;
    }
    // Getters
    public 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;
    }
    // Getters
    public 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 {
    @Override
    public void onApplicationEvent(UserRegisteredEvent event) {
        System.out.println("发送欢迎邮件给: " + event.getEmail());
        // 实际邮件发送逻辑
    }
}
@Component
public class OrderProcessingListener implements ApplicationListener {
    @Override
    public 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 {
    // 监听用户注册事件
    @EventListener
    public void handleUserRegistered(UserRegisteredEvent event) {
        System.out.println("记录用户注册日志: " + event.getUsername());
        // 日志记录逻辑
    }
    // 监听订单创建事件(异步执行)
    @Async
    @EventListener
    public 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") // 指定线程池
    @EventListener
    public 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)
    @EventListener
    public void firstListener(UserRegisteredEvent event) {
        System.out.println("第一个监听器执行");
    }
    @Order(2)
    @EventListener
    public void secondListener(UserRegisteredEvent event) {
        System.out.println("第二个监听器执行");
    }
    @Order(Ordered.LOWEST_PRECEDENCE) // 最低优先级
    @EventListener
    public void lastListener(UserRegisteredEvent event) {
        System.out.println("最后一个监听器执行");
    }
}

四、注意事项

  1. 事件命名规范

    • 使用过去时态表示已完成的事件:UserRegisteredEvent, OrderCreatedEvent
    • 保持事件类名清晰表达业务含义
  2. 事件内容设计

    • 包含足够的信息供监听器处理
    • 避免包含大型对象或敏感数据
    • 保持事件对象不可变
  3. 错误处理

    @EventListener
    public void handleEventWithError(UserRegisteredEvent event) {
        try {
            // 业务逻辑
        } catch (Exception e) {
            // 记录错误并处理
            System.err.println("处理事件失败: " + e.getMessage());
            // 可选择重试或通知监控系统
        }
    }
  4. 性能优化

    • 对于耗时操作使用异步监听
    • 根据业务需求合理设置线程池参数
    • 避免在事件处理中执行阻塞操作

五、完整示例:用户注册流程

// 事件定义
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;
    }
    @Transactional
    public 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
    @EventListener
    public void sendWelcomeEmail(UserRegisteredEvent event) {
        User user = event.getUser();
        emailService.sendWelcomeEmail(user.getEmail(), user.getUsername());
    }
    // 初始化用户资料
    @EventListener
    public 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 事件机制提供了强大的解耦能力,通过事件驱动架构可以实现:

  1. 业务解耦:分离核心业务与辅助功能
  2. 可扩展性:轻松添加新功能而不修改现有代码
  3. 异步处理:提高系统响应速度
  4. 事务管理:精确控制事件处理时机

在实际应用中,应根据业务需求合理选择同步/异步处理、事务绑定等特性,并注意事件对象的合理设计和错误处理机制。

posted on 2025-09-30 15:20  ljbguanli  阅读(46)  评论(0)    收藏  举报