Spring Event案例

wen java案例 2

本文目录导读:

Spring Event案例

  1. Spring Event基础概念
  2. 实战案例:用户注册系统
  3. 高级特性案例
  4. 测试案例
  5. Controller示例
  6. 生产环境配置建议
  7. 最佳实践

我将为您全面介绍Spring Event的实战案例,从基础到进阶,包含完整的代码示例。

Spring Event基础概念

1 核心组件

  • 事件(Event):继承ApplicationEvent的对象
  • 监听器(Listener):处理事件的对象
  • 发布器(Publisher):发布事件的对象
  • 事件广播器(Multicaster):Spring内部用于管理监听器的组件

实战案例:用户注册系统

1 项目结构

com.example.eventdemo
├── event
│   ├── UserRegisterEvent.java
│   └── OrderEvent.java
├── listener
│   ├── EmailListener.java
│   ├── SmsListener.java
│   ├── CouponListener.java
│   └── LogListener.java
├── service
│   ├── UserService.java
│   └── OrderService.java
└── controller
    └── DemoController.java

2 事件定义

// 用户注册事件
public class UserRegisterEvent extends ApplicationEvent {
    private final String username;
    private final String email;
    private final String phone;
    private final Date registerTime;
    public UserRegisterEvent(Object source, String username, String email, String phone) {
        super(source);
        this.username = username;
        this.email = email;
        this.phone = phone;
        this.registerTime = new Date();
    }
    // getter/setter 方法
    public String getUsername() { return username; }
    public String getEmail() { return email; }
    public String getPhone() { return phone; }
    public Date getRegisterTime() { return registerTime; }
}
// 订单创建事件
public class OrderEvent extends ApplicationEvent {
    private final Long orderId;
    private final BigDecimal amount;
    private final Long userId;
    public OrderEvent(Object source, Long orderId, BigDecimal amount, Long userId) {
        super(source);
        this.orderId = orderId;
        this.amount = amount;
        this.userId = userId;
    }
    // getter/setter 方法
    public Long getOrderId() { return orderId; }
    public BigDecimal getAmount() { return amount; }
    public Long getUserId() { return userId; }
}

3 服务层实现

@Service
@Slf4j
public class UserService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    /**
     * 用户注册
     */
    @Transactional
    public void registerUser(String username, String email, String phone) {
        // 1. 保存用户信息到数据库
        log.info("保存用户信息: {}, {}, {}", username, email, phone);
        // 2. 发布用户注册事件
        UserRegisterEvent event = new UserRegisterEvent(this, username, email, phone);
        eventPublisher.publishEvent(event);
        log.info("用户注册完成,事件已发布");
    }
}
@Service
@Slf4j
public class OrderService {
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    /**
     * 创建订单
     */
    @Transactional
    public void createOrder(Long userId, BigDecimal amount) {
        // 1. 创建订单
        Long orderId = System.currentTimeMillis();
        log.info("创建订单: orderId={}, userId={}, amount={}", orderId, userId, amount);
        // 2. 发布订单事件
        OrderEvent event = new OrderEvent(this, orderId, amount, userId);
        eventPublisher.publishEvent(event);
        log.info("订单创建完成,事件已发布");
    }
}

4 监听器实现

// 邮件监听器 - 同步处理
@Component
@Slf4j
public class EmailListener {
    @EventListener
    @Async("taskExecutor")
    public void handleUserRegisterEvent(UserRegisterEvent event) {
        log.info("发送欢迎邮件给用户: {}", event.getUsername());
        // 模拟邮件发送
        try {
            Thread.sleep(1000);
            log.info("邮件发送成功: {} -> {}", event.getEmail(), event.getUsername());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("邮件发送失败", e);
        }
    }
}
// 短信监听器
@Component
@Slf4j
public class SmsListener {
    @EventListener
    @Async("taskExecutor")
    public void handleUserRegisterEvent(UserRegisterEvent event) {
        log.info("发送注册成功短信: {}", event.getPhone());
        // 模拟短信发送
        try {
            Thread.sleep(500);
            log.info("短信发送成功: {} -> {}", event.getPhone(), event.getUsername());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            log.error("短信发送失败", e);
        }
    }
}
// 优惠券监听器
@Component
@Slf4j
public class CouponListener {
    @EventListener
    @Async("taskExecutor")
    public void handleUserRegisterEvent(UserRegisterEvent event) {
        log.info("发送新人优惠券给用户: {}", event.getUsername());
        // 模拟优惠券发放
        log.info("优惠券发放成功: 用户{}获得100元新人礼包", event.getUsername());
    }
    @EventListener
    @Async("taskExecutor")
    public void handleOrderEvent(OrderEvent event) {
        if (event.getAmount().compareTo(new BigDecimal("1000")) > 0) {
            log.info("订单金额超过1000元,发放VIP优惠券: orderId={}", event.getOrderId());
        }
    }
}
// 日志监听器 - 同步处理
@Component
@Slf4j
public class LogListener {
    @EventListener
    public void handleUserRegisterEvent(UserRegisterEvent event) {
        log.info("记录用户注册日志: {}", event.getUsername());
    }
    @EventListener
    @Order(1)  // 设置执行顺序
    public void handleOrderEvent(OrderEvent event) {
        log.info("记录订单创建日志: orderId={}", event.getOrderId());
    }
}

5 异步配置

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    @Override
    @Bean("taskExecutor")
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        executor.setThreadNamePrefix("event-thread-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, objects) -> {
            log.error("异步事件处理异常: {}, 方法: {}", throwable.getMessage(), method.getName());
        };
    }
}

高级特性案例

1 条件事件监听

@Component
@Slf4j
public class ConditionalListener {
    /**
     * 只有特定条件下才处理事件
     */
    @EventListener
    @ConditionalOnProperty(name = "app.notification.email.enabled", havingValue = "true")
    public void conditionalHandle(UserRegisterEvent event) {
        log.info("邮件通知已启用,发送邮件给: {}", event.getEmail());
    }
}

2 指定监听器ID

@Component
@Slf4j
public class CustomizedListener {
    @EventListener
    public void handleEvent(UserRegisterEvent event) {
        // 通过 @Order 控制顺序
    }
    // 使用泛型事件
    @EventListener
    public void handleGenericEvent(MyEntityEvent<Order> event) {
        Order order = event.getData();
        log.info("处理订单泛型事件: {}", order);
    }
}
// 泛型事件类
public class MyEntityEvent<T> extends ApplicationEvent {
    private final T data;
    public MyEntityEvent(Object source, T data) {
        super(source);
        this.data = data;
    }
    public T getData() { return data; }
}

3 事务事件监听

@Component
@Slf4j
public class TransactionalListener {
    /**
     * 事务提交后处理
     * @TransactionalEventListener 默认为 AFTER_COMMIT
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void handleAfterCommit(UserRegisterEvent event) {
        log.info("事务提交后发送邮件: {}", event.getUsername());
    }
    @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
    public void handleAfterRollback(UserRegisterEvent event) {
        log.info("事务回滚后记录日志: {}", event.getUsername());
    }
    @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
    public void handleBeforeCommit(UserRegisterEvent event) {
        log.info("事务提交前处理: {}", event.getUsername());
    }
}

4 事件异常处理

@Configuration
@Slf4j
public class EventExceptionConfig {
    @Bean
    public ApplicationListener<ApplicationEvent> eventListener() {
        return event -> {
            try {
                // 自定义事件处理逻辑
                handleEvent(event);
            } catch (Exception e) {
                log.error("事件处理异常: {}", event.getClass().getSimpleName(), e);
            }
        };
    }
    /**
     * 事件监听器工厂,可以添加自定义的后处理器
     */
    @Bean
    public EventListenerFactory eventListenerFactory(ApplicationContext context) {
        DefaultEventListenerFactory factory = new DefaultEventListenerFactory();
        factory.setOrder(Ordered.LOWEST_PRECEDENCE);
        return factory;
    }
}

测试案例

@SpringBootTest
@Slf4j
public class EventTest {
    @Autowired
    private UserService userService;
    @Autowired
    private OrderService orderService;
    @Test
    public void testUserRegisterEvent() throws InterruptedException {
        log.info("开始测试用户注册事件");
        userService.registerUser("张三", "zhangsan@example.com", "13800138000");
        // 等待异步事件处理完成
        Thread.sleep(3000);
        log.info("用户注册事件测试完成");
    }
    @Test
    public void testOrderEvent() throws InterruptedException {
        log.info("开始测试订单事件");
        orderService.createOrder(1L, new BigDecimal("1500.00"));
        Thread.sleep(2000);
        log.info("订单事件测试完成");
    }
}

Controller示例

@RestController
@RequestMapping("/api/demo")
@Slf4j
public class DemoController {
    @Autowired
    private UserService userService;
    @Autowired
    private OrderService orderService;
    @PostMapping("/register")
    public Result register(@RequestBody RegisterRequest request) {
        userService.registerUser(request.getUsername(), request.getEmail(), request.getPhone());
        return Result.success("注册成功");
    }
    @PostMapping("/order")
    public Result createOrder(@RequestBody OrderRequest request) {
        orderService.createOrder(request.getUserId(), request.getAmount());
        return Result.success("下单成功");
    }
}

生产环境配置建议

# application.yml
spring:
  task:
    execution:
      pool:
        core-size: 8
        max-size: 16
        queue-capacity: 200
        keep-alive: 60s
      thread-name-prefix: event-executor-
  application:
    name: event-demo
logging:
  level:
    com.example.eventdemo: DEBUG
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"

最佳实践

1 事件命名规范

// 使用过去时态命名事件
UserRegisteredEvent  // 推荐
UserRegisterEvent   // 可以接受
RegisterUserEvent   // 不推荐

2 监听器设计原则

@Component
@Slf4j
public class RecommendedListener {
    /**
     * 1. 监听器应该保持轻量级
     * 2. 异常应该被捕获,不影响其他监听器
     * 3. 考虑使用 @Async 处理耗时操作
     */
    @EventListener
    @Async("taskExecutor")
    public void handleEvent(UserRegisterEvent event) {
        try {
            log.info("处理事件: {}", event.getUsername());
            // 业务处理
        } catch (Exception e) {
            log.error("事件处理失败", e);
        }
    }
}

3 监控和性能

@Component
@Aspect
@Slf4j
public class EventMonitor {
    @Around("@annotation(org.springframework.context.event.EventListener)")
    public Object monitorEvent(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        try {
            Object result = joinPoint.proceed();
            long duration = System.currentTimeMillis() - start;
            log.info("事件处理耗时: {} ms", duration);
            return result;
        } catch (Exception e) {
            log.error("事件处理异常: {}", e.getMessage(), e);
            throw e;
        }
    }
}

Spring Event提供了:

  • 解耦:业务组件之间松耦合
  • 异步处理:提高系统响应速度
  • 顺序控制:@Order注解控制监听器执行顺序
  • 事务集成:@TransactionalEventListener支持事务边界
  • 泛型支持:支持泛型事件类型

通过合理使用Spring Event,可以有效提升代码的维护性和扩展性。

抱歉,评论功能暂时关闭!