1. 观察者模式:程序世界的"消息通知系统"
想象一下微信群聊的场景:当有人在群里发消息时,所有群成员都会收到通知。这种"一对多"的消息传递机制,在软件设计中就是观察者模式的典型应用。
观察者模式(Observer Pattern)是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象(被观察者)状态改变时,所有依赖它的对象(观察者)都会自动收到通知并更新。
// 技术栈:纯Java实现观察者模式
// 1. 定义观察者接口
interface MessageObserver {
void update(String message); // 当被观察者状态变化时调用
}
// 2. 定义被观察者(主题)
class MessageSubject {
private List<MessageObserver> observers = new ArrayList<>();
private String message;
// 添加观察者
public void addObserver(MessageObserver observer) {
observers.add(observer);
}
// 移除观察者
public void removeObserver(MessageObserver observer) {
observers.remove(observer);
}
// 通知所有观察者
public void notifyObservers() {
for (MessageObserver observer : observers) {
observer.update(message);
}
}
// 状态改变方法
public void setMessage(String message) {
this.message = message;
notifyObservers(); // 状态改变后自动通知观察者
}
}
// 3. 实现具体观察者
class UserObserver implements MessageObserver {
private String name;
public UserObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " 收到新消息: " + message);
}
}
// 使用示例
public class ObserverDemo {
public static void main(String[] args) {
MessageSubject subject = new MessageSubject();
// 创建三个观察者
MessageObserver alice = new UserObserver("Alice");
MessageObserver bob = new UserObserver("Bob");
MessageObserver charlie = new UserObserver("Charlie");
// 注册观察者
subject.addObserver(alice);
subject.addObserver(bob);
subject.addObserver(charlie);
// 改变状态,自动通知观察者
subject.setMessage("今晚7点开会");
// 输出:
// Alice 收到新消息: 今晚7点开会
// Bob 收到新消息: 今晚7点开会
// Charlie 收到新消息: 今晚7点开会
}
}
2. Spring事件机制:企业级的观察者实现
Spring框架对观察者模式进行了优雅的封装,提供了更加强大和便捷的事件机制。这套机制基于ApplicationContext,主要由三个核心组件构成:
- ApplicationEvent:所有事件的父类,自定义事件需要继承它
- ApplicationListener:事件监听器接口
- ApplicationEventPublisher:事件发布接口
// 技术栈:Spring框架事件机制
// 1. 定义自定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private String orderId;
private String customerName;
public OrderCreatedEvent(Object source, String orderId, String customerName) {
super(source);
this.orderId = orderId;
this.customerName = customerName;
}
// getter方法
public String getOrderId() { return orderId; }
public String getCustomerName() { return customerName; }
}
// 2. 创建事件监听器
@Component
public class OrderEventListener {
// 方式1:实现ApplicationListener接口
@Component
public static class EmailListener implements ApplicationListener<OrderCreatedEvent> {
@Override
public void onApplicationEvent(OrderCreatedEvent event) {
System.out.println("发送邮件给 " + event.getCustomerName() +
", 订单ID: " + event.getOrderId());
}
}
// 方式2:使用@EventListener注解(更简洁)
@EventListener
public void handleOrderCreated(OrderCreatedEvent event) {
System.out.println("记录订单日志: " + event.getOrderId());
}
// 可以监听多个事件
@EventListener
public void handleMultipleEvents(OrderCreatedEvent event) {
System.out.println("处理订单创建后的其他业务: " + event.getOrderId());
}
}
// 3. 发布事件的服务
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void createOrder(String orderId, String customerName) {
System.out.println("创建订单: " + orderId);
// 发布订单创建事件
eventPublisher.publishEvent(
new OrderCreatedEvent(this, orderId, customerName));
}
}
// 4. 测试类
@SpringBootTest
public class OrderServiceTest {
@Autowired
private OrderService orderService;
@Test
public void testOrderEvent() {
orderService.createOrder("ORD-12345", "张三");
// 输出:
// 创建订单: ORD-12345
// 发送邮件给 张三, 订单ID: ORD-12345
// 记录订单日志: ORD-12345
// 处理订单创建后的其他业务: ORD-12345
}
}
3. 高级应用:异步事件与条件监听
Spring的事件机制还支持异步处理和条件过滤,让事件处理更加灵活强大。
// 技术栈:Spring框架高级事件特性
// 1. 异步事件配置
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.initialize();
return executor;
}
}
// 2. 异步事件监听
@Component
public class AsyncOrderListener {
@Async // 标记为异步处理
@EventListener
public void asyncHandleOrder(OrderCreatedEvent event) {
System.out.println("异步处理订单: " + event.getOrderId() +
", 线程: " + Thread.currentThread().getName());
}
}
// 3. 条件监听
@Component
public class ConditionalListener {
// 只有当订单ID以VIP开头时才处理
@EventListener(condition = "#event.orderId.startsWith('VIP')")
public void handleVipOrder(OrderCreatedEvent event) {
System.out.println("处理VIP订单: " + event.getOrderId());
}
// 使用SpEL表达式进行复杂条件判断
@EventListener(condition = "#event.customerName != null && #event.customerName.length() > 3")
public void handleLongNameOrder(OrderCreatedEvent event) {
System.out.println("处理长名字客户的订单: " + event.getCustomerName());
}
}
// 4. 测试异步和条件监听
@SpringBootTest
public class AdvancedEventTest {
@Autowired
private OrderService orderService;
@Test
public void testAdvancedEvents() {
System.out.println("主线程: " + Thread.currentThread().getName());
orderService.createOrder("VIP-1001", "李四");
orderService.createOrder("NORMAL-2002", "王");
orderService.createOrder("VIP-3003", "赵五");
// 给异步处理一点时间完成
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
/* 可能的输出(顺序可能不同,因为异步):
主线程: main
创建订单: VIP-1001
发送邮件给 李四, 订单ID: VIP-1001
记录订单日志: VIP-1001
处理VIP订单: VIP-1001
处理长名字客户的订单: 李四
处理订单创建后的其他业务: VIP-1001
异步处理订单: VIP-1001, 线程: task-1
创建订单: NORMAL-2002
发送邮件给 王, 订单ID: NORMAL-2002
记录订单日志: NORMAL-2002
处理订单创建后的其他业务: NORMAL-2002
异步处理订单: NORMAL-2002, 线程: task-2
创建订单: VIP-3003
发送邮件给 赵五, 订单ID: VIP-3003
记录订单日志: VIP-3003
处理VIP订单: VIP-3003
处理长名字客户的订单: 赵五
处理订单创建后的其他业务: VIP-3003
异步处理订单: VIP-3003, 线程: task-3
*/
}
4. 应用场景分析
观察者模式和Spring事件机制在实际开发中有着广泛的应用场景:
- 业务解耦:订单创建后需要触发多种操作(发邮件、发短信、更新库存等)
- 系统监控:当系统出现异常时通知监控系统
- 缓存更新:数据变更时通知缓存系统更新
- 分布式系统:微服务间的事件通知
- 用户通知:站内信、推送通知等场景
- 业务流程:工作流引擎中的状态变更通知
5. 技术优缺点对比
纯Java观察者模式
优点:
- 不依赖任何框架,纯Java实现
- 理解简单,实现直接
- 适合小型项目或框架不支持的环境
缺点:
- 需要手动管理观察者的注册和注销
- 缺乏高级功能如异步处理、条件过滤
- 观察者和被观察者仍有代码耦合
Spring事件机制
优点:
- 与Spring生态无缝集成
- 支持异步事件处理
- 支持条件过滤监听
- 自动管理监听器,无需手动注册
- 更好的解耦,发布者不需要知道监听器的存在
缺点:
- 需要Spring环境支持
- 对于简单场景可能显得"过重"
- 异步处理需要额外配置
6. 使用注意事项
- 事件设计:事件对象应包含足够的信息,但不要包含太多业务逻辑
- 性能考虑:对于耗时操作,考虑使用异步处理
- 异常处理:监听器中的异常需要妥善处理,避免影响主流程
- 循环依赖:避免事件发布导致的事件循环
- 事务边界:注意事件发布与事务的关系,考虑使用
@TransactionalEventListener - 监听器顺序:需要控制监听器执行顺序时,可以使用
@Order注解
7. 关联技术扩展
Spring的事件机制还可以与其他技术结合使用:
- 与Spring Cloud Stream结合:将本地事件转换为消息队列事件
- 与Spring Data结合:在数据变更时发布事件
- 与Spring Security结合:处理安全相关事件
- 与React式编程结合:使用
Reactive风格处理事件流
8. 总结
观察者模式是解耦系统组件的重要设计模式,而Spring事件机制则为企业级应用提供了更加完善的事件驱动编程支持。通过合理使用这些技术,可以构建出松耦合、易扩展的应用程序架构。
在实际项目中,建议:
- 简单场景可以直接使用Java的观察者模式
- Spring项目优先使用Spring事件机制
- 耗时操作使用异步事件处理
- 合理设计事件对象,避免过度设计
- 注意事务和异常处理等边界情况
评论