📡 Spring事件机制:观察者模式的完美实现!

31 阅读7分钟

副标题:解耦神器,让组件间通信更优雅!🎯


🎬 开场:什么是事件机制?

传统方式 vs 事件机制

场景:用户注册后,需要发送邮件、短信、积分等

传统方式(紧耦合):

@Service
public class UserService {
    
    @Autowired
    private EmailService emailService;
    
    @Autowired
    private SmsService smsService;
    
    @Autowired
    private PointService pointService;
    
    public void register(User user) {
        // 保存用户
        userMapper.insert(user);
        
        // 发送邮件
        emailService.sendWelcomeEmail(user);
        
        // 发送短信
        smsService.sendWelcomeSms(user);
        
        // 赠送积分
        pointService.givePoints(user);
        
        // 如果需要添加新功能,必须修改这里 ❌
    }
}

问题:
- UserService依赖太多服务
- 高耦合
- 难以扩展


事件机制(解耦):

@Service
public class UserService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    public void register(User user) {
        // 保存用户
        userMapper.insert(user);
        
        // 发布事件
        eventPublisher.publishEvent(new UserRegisterEvent(user));
        
        // 不关心后续处理 ✅
    }
}

// 邮件服务监听事件
@Component
public class EmailListener {
    
    @EventListener
    public void handleUserRegister(UserRegisterEvent event) {
        emailService.sendWelcomeEmail(event.getUser());
    }
}

// 短信服务监听事件
@Component
public class SmsListener {
    
    @EventListener
    public void handleUserRegister(UserRegisterEvent event) {
        smsService.sendWelcomeSms(event.getUser());
    }
}

优点:
- UserService只关心发布事件
- 低耦合
- 易于扩展(添加监听器即可)✅

📚 Spring事件机制组成

核心组件

Spring事件机制(4个核心):

1. ApplicationEvent(事件)
   - 自定义事件类
   - 继承ApplicationEvent

2. ApplicationEventPublisher(事件发布器)
   - 发布事件
   - publishEvent()方法

3. ApplicationListener(事件监听器)
   - 监听事件
   - onApplicationEvent()方法

4. ApplicationEventMulticaster(事件多播器)
   - 管理监听器
   - 广播事件

🎯 基本使用

1️⃣ 定义事件

/**
 * 用户注册事件
 */
public class UserRegisterEvent extends ApplicationEvent {
    
    private User user;
    
    public UserRegisterEvent(Object source, User user) {
        super(source);
        this.user = user;
    }
    
    public User getUser() {
        return user;
    }
}

/**
 * Spring 4.2+:不继承ApplicationEvent也可以
 */
public class OrderCreatedEvent {
    
    private Order order;
    
    public OrderCreatedEvent(Order order) {
        this.order = order;
    }
    
    public Order getOrder() {
        return order;
    }
}

2️⃣ 发布事件

/**
 * 发布事件的方式
 */
@Service
public class UserService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;  // 方式1:注入发布器
    
    // 或者
    
    @Autowired
    private ApplicationContext applicationContext;  // 方式2:注入容器
    
    /**
     * 用户注册
     */
    public void register(User user) {
        // 保存用户
        userMapper.insert(user);
        
        // 方式1:使用ApplicationEventPublisher
        eventPublisher.publishEvent(new UserRegisterEvent(this, user));
        
        // 方式2:使用ApplicationContext
        // applicationContext.publishEvent(new UserRegisterEvent(this, user));
        
        System.out.println("用户注册完成");
    }
}

3️⃣ 监听事件

/**
 * 监听事件的方式
 */

// 方式1:实现ApplicationListener接口
@Component
public class UserRegisterListener implements ApplicationListener<UserRegisterEvent> {
    
    @Override
    public void onApplicationEvent(UserRegisterEvent event) {
        User user = event.getUser();
        System.out.println("监听到用户注册事件:" + user.getUsername());
        
        // 处理业务逻辑
    }
}

// 方式2:使用@EventListener注解(推荐)
@Component
public class EmailListener {
    
    @EventListener
    public void handleUserRegister(UserRegisterEvent event) {
        User user = event.getUser();
        System.out.println("发送欢迎邮件:" + user.getEmail());
        
        // 发送邮件
        emailService.sendWelcomeEmail(user);
    }
}

@Component
public class SmsListener {
    
    @EventListener
    public void handleUserRegister(UserRegisterEvent event) {
        User user = event.getUser();
        System.out.println("发送欢迎短信:" + user.getPhone());
        
        // 发送短信
        smsService.sendWelcomeSms(user);
    }
}

🔍 高级特性

条件监听

/**
 * 条件监听:只在特定条件下触发
 */
@Component
public class ConditionalListener {
    
    /**
     * 只监听VIP用户的注册事件
     */
    @EventListener(condition = "#event.user.vip == true")
    public void handleVipRegister(UserRegisterEvent event) {
        System.out.println("VIP用户注册");
        
        // VIP专属处理
    }
    
    /**
     * 只监听订单金额大于1000的事件
     */
    @EventListener(condition = "#event.order.amount > 1000")
    public void handleLargeOrder(OrderCreatedEvent event) {
        System.out.println("大额订单");
        
        // 大额订单特殊处理
    }
}

异步监听

/**
 * 异步监听事件
 */
@Configuration
@EnableAsync  // 启用异步
public class AsyncConfig {
}

@Component
public class AsyncListener {
    
    /**
     * 异步监听
     */
    @Async
    @EventListener
    public void handleUserRegister(UserRegisterEvent event) {
        System.out.println("异步处理,线程:" + Thread.currentThread().getName());
        
        // 耗时操作(不阻塞主线程)
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("异步处理完成");
    }
}

事件监听顺序

/**
 * 指定监听器执行顺序
 */
@Component
public class OrderedListener {
    
    @EventListener
    @Order(1)  // 优先级1(数字越小优先级越高)
    public void listener1(UserRegisterEvent event) {
        System.out.println("监听器1执行");
    }
    
    @EventListener
    @Order(2)  // 优先级2
    public void listener2(UserRegisterEvent event) {
        System.out.println("监听器2执行");
    }
    
    @EventListener
    @Order(3)  // 优先级3
    public void listener3(UserRegisterEvent event) {
        System.out.println("监听器3执行");
    }
}

/**
 * 输出:
 * 监听器1执行
 * 监听器2执行
 * 监听器3执行
 */

事务监听

/**
 * 事务监听:在事务的特定阶段执行
 */
@Component
public class TransactionalListener {
    
    /**
     * 事务提交后执行
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    public void afterCommit(UserRegisterEvent event) {
        System.out.println("事务提交后:发送通知");
        
        // 事务成功提交后才发送通知
        notificationService.send(event.getUser());
    }
    
    /**
     * 事务回滚后执行
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
    public void afterRollback(UserRegisterEvent event) {
        System.out.println("事务回滚后:记录日志");
        
        // 事务回滚后记录日志
        logService.log("用户注册失败");
    }
    
    /**
     * 事务完成后执行(无论提交还是回滚)
     */
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
    public void afterCompletion(UserRegisterEvent event) {
        System.out.println("事务完成后:清理资源");
    }
}

/**
 * 事务阶段:
 * - BEFORE_COMMIT:事务提交前
 * - AFTER_COMMIT:事务提交后(默认)
 * - AFTER_ROLLBACK:事务回滚后
 * - AFTER_COMPLETION:事务完成后(提交或回滚)
 */

🎯 实现原理

源码分析

/**
 * ApplicationEventPublisher:事件发布器接口
 */
@FunctionalInterface
public interface ApplicationEventPublisher {
    
    /**
     * 发布事件
     */
    void publishEvent(Object event);
}

/**
 * ApplicationContext实现了ApplicationEventPublisher
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader
        implements ConfigurableApplicationContext {
    
    /**
     * 事件多播器
     */
    private ApplicationEventMulticaster applicationEventMulticaster;
    
    /**
     * 发布事件
     */
    @Override
    public void publishEvent(Object event) {
        publishEvent(event, null);
    }
    
    protected void publishEvent(Object event, ResolvableType eventType) {
        // 1. 包装事件
        ApplicationEvent applicationEvent;
        if (event instanceof ApplicationEvent) {
            applicationEvent = (ApplicationEvent) event;
        } else {
            applicationEvent = new PayloadApplicationEvent<>(this, event);
            if (eventType == null) {
                eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
            }
        }
        
        // 2. 多播事件
        if (this.applicationEventMulticaster != null) {
            this.applicationEventMulticaster.multicastEvent(applicationEvent, eventType);
        }
        
        // 3. 发布到父容器
        if (this.parent != null) {
            if (this.parent instanceof AbstractApplicationContext) {
                ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
            } else {
                this.parent.publishEvent(event);
            }
        }
    }
}

/**
 * ApplicationEventMulticaster:事件多播器
 */
public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
    
    /**
     * 多播事件
     */
    @Override
    public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
        
        Executor executor = getTaskExecutor();
        
        // 获取所有监听器
        for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            if (executor != null) {
                // 异步执行
                executor.execute(() -> invokeListener(listener, event));
            } else {
                // 同步执行
                invokeListener(listener, event);
            }
        }
    }
    
    /**
     * 调用监听器
     */
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
        ErrorHandler errorHandler = getErrorHandler();
        if (errorHandler != null) {
            try {
                doInvokeListener(listener, event);
            } catch (Throwable err) {
                errorHandler.handleError(err);
            }
        } else {
            doInvokeListener(listener, event);
        }
    }
    
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
        try {
            listener.onApplicationEvent(event);
        } catch (ClassCastException ex) {
            // 类型不匹配,忽略
        }
    }
}

💻 实战案例

案例1:用户注册完整流程

/**
 * 用户注册事件
 */
public class UserRegisterEvent extends ApplicationEvent {
    
    private User user;
    
    public UserRegisterEvent(Object source, User user) {
        super(source);
        this.user = user;
    }
    
    public User getUser() {
        return user;
    }
}

/**
 * 用户服务:发布事件
 */
@Service
public class UserService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    @Autowired
    private UserMapper userMapper;
    
    /**
     * 用户注册
     */
    @Transactional
    public void register(RegisterRequest request) {
        // 1. 保存用户
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setPhone(request.getPhone());
        user.setCreateTime(new Date());
        
        userMapper.insert(user);
        
        // 2. 发布事件
        eventPublisher.publishEvent(new UserRegisterEvent(this, user));
        
        System.out.println("用户注册完成");
    }
}

/**
 * 邮件监听器
 */
@Component
public class EmailListener {
    
    @Autowired
    private EmailService emailService;
    
    @Async
    @EventListener
    @Order(1)
    public void handleUserRegister(UserRegisterEvent event) {
        User user = event.getUser();
        
        System.out.println("发送欢迎邮件:" + user.getEmail());
        
        // 发送邮件
        emailService.sendWelcomeEmail(
            user.getEmail(),
            "欢迎注册",
            "欢迎您," + user.getUsername() + "!"
        );
    }
}

/**
 * 短信监听器
 */
@Component
public class SmsListener {
    
    @Autowired
    private SmsService smsService;
    
    @Async
    @EventListener
    @Order(2)
    public void handleUserRegister(UserRegisterEvent event) {
        User user = event.getUser();
        
        System.out.println("发送欢迎短信:" + user.getPhone());
        
        // 发送短信
        smsService.sendWelcomeSms(
            user.getPhone(),
            "欢迎注册!"
        );
    }
}

/**
 * 积分监听器
 */
@Component
public class PointListener {
    
    @Autowired
    private PointService pointService;
    
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
    @Order(3)
    public void handleUserRegister(UserRegisterEvent event) {
        User user = event.getUser();
        
        System.out.println("赠送注册积分");
        
        // 赠送积分
        pointService.givePoints(user.getId(), 100, "注册奖励");
    }
}

/**
 * 日志监听器
 */
@Component
public class LogListener {
    
    @Autowired
    private LogService logService;
    
    @Async
    @EventListener
    @Order(4)
    public void handleUserRegister(UserRegisterEvent event) {
        User user = event.getUser();
        
        System.out.println("记录操作日志");
        
        // 记录日志
        logService.log("用户注册", "userId=" + user.getId());
    }
}

案例2:订单状态变更

/**
 * 订单状态变更事件
 */
public class OrderStatusChangedEvent extends ApplicationEvent {
    
    private Order order;
    private OrderStatus oldStatus;
    private OrderStatus newStatus;
    
    public OrderStatusChangedEvent(Object source, Order order, 
                                  OrderStatus oldStatus, OrderStatus newStatus) {
        super(source);
        this.order = order;
        this.oldStatus = oldStatus;
        this.newStatus = newStatus;
    }
    
    // getter...
}

/**
 * 订单服务
 */
@Service
public class OrderService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    /**
     * 更新订单状态
     */
    @Transactional
    public void updateStatus(Long orderId, OrderStatus newStatus) {
        // 1. 查询订单
        Order order = orderMapper.selectById(orderId);
        OrderStatus oldStatus = order.getStatus();
        
        // 2. 更新状态
        order.setStatus(newStatus);
        orderMapper.updateById(order);
        
        // 3. 发布事件
        eventPublisher.publishEvent(
            new OrderStatusChangedEvent(this, order, oldStatus, newStatus)
        );
    }
}

/**
 * 订单状态监听器
 */
@Component
public class OrderStatusListener {
    
    /**
     * 订单支付成功
     */
    @EventListener(condition = "#event.newStatus.name() == 'PAID'")
    public void handleOrderPaid(OrderStatusChangedEvent event) {
        Order order = event.getOrder();
        System.out.println("订单支付成功:" + order.getOrderNo());
        
        // 减库存、发货等
    }
    
    /**
     * 订单已发货
     */
    @EventListener(condition = "#event.newStatus.name() == 'SHIPPED'")
    public void handleOrderShipped(OrderStatusChangedEvent event) {
        Order order = event.getOrder();
        System.out.println("订单已发货:" + order.getOrderNo());
        
        // 发送物流通知
    }
    
    /**
     * 订单已完成
     */
    @EventListener(condition = "#event.newStatus.name() == 'COMPLETED'")
    public void handleOrderCompleted(OrderStatusChangedEvent event) {
        Order order = event.getOrder();
        System.out.println("订单已完成:" + order.getOrderNo());
        
        // 增加积分、评价提醒等
    }
}

🎉 总结

核心要点

1. 事件驱动
   - 发布-订阅模式
   - 解耦

2. 三个核心
   - ApplicationEvent:事件
   - ApplicationEventPublisher:发布器
   - ApplicationListener:监听器

3. 高级特性
   - 条件监听
   - 异步监听
   - 事务监听
   - 执行顺序

4. 使用场景
   - 用户注册
   - 订单处理
   - 日志记录
   - 统计分析

最佳实践

1. 事件命名
   - XxxEvent
   - 明确语义

2. 监听器命名
   - XxxListener
   - 单一职责

3. 异步处理
   - 耗时操作使用@Async
   - 不阻塞主流程

4. 事务处理
   - 使用@TransactionalEventListener
   - 在正确的阶段执行

5. 异常处理
   - 监听器中捕获异常
   - 不影响其他监听器

记忆口诀

Spring事件机制好,
观察者模式巧妙。

三个核心要记牢:
ApplicationEvent事件,
ApplicationEventPublisher发布器,
ApplicationListener监听器。

发布事件很简单,
publishEvent方法调。
监听事件两方式,
接口实现或注解。

@EventListener注解用,
方法参数是事件。
condition条件过滤,
精准监听更高效。

@Async异步执行,
耗时操作不阻塞。
@Order指定顺序,
监听器按序执行。

@TransactionalEventListener特殊,
事务阶段来执行。
AFTER_COMMIT提交后,
AFTER_ROLLBACK回滚后。

事件驱动解耦好,
扩展维护都方便。
用户注册和订单,
事件机制来实现!

愿你的组件间通信优雅解耦,事件驱动设计精妙! 📡✨