Spring、事件总线和中介者模式有什么关系?
简化版
Spring 容器、事件总线、消息中心都可能体现中介者思想:对象不直接互相依赖,而是通过容器或事件机制协作。但它们不一定严格等于中介者模式,因为它们还包含依赖注入、生命周期、发布订阅、异步处理等更大的框架能力。
详细版
可以这样理解:
- Spring IoC 容器:对象依赖由容器装配,减少手动创建和直接耦合,但 IoC 本身不是中介者模式;
- Spring ApplicationEvent:发布者发布事件,监听器响应事件,更接近观察者/发布订阅;
- 事件总线:模块之间通过事件通信,可以减少直接依赖,有中介者思想;
- 业务协调服务:如果一个服务集中协调多个组件交互,更像中介者模式。
面试时要谨慎表达:框架机制可以体现某些设计模式思想,但不能把整个 Spring 简单说成中介者模式。
完整版教学
一、为什么会问 Spring 和中介者模式
面试官问这个问题,通常不是要你背“Spring 用了哪些设计模式”,而是想看你能不能区分:
- 设计模式的意图;
- 框架机制的实现;
- 真实项目里的相似思想。
很多框架都不是某一个模式的简单套用,而是多种模式和架构思想的组合。
二、Spring IoC 和中介者模式的关系
Spring IoC 容器负责创建对象、管理依赖、注入 Bean。
这能减少对象之间手动创建的耦合:
class OrderService {
private final PayService payService;
public OrderService(PayService payService) {
this.payService = payService;
}
}
OrderService 不需要自己 new PayService(),依赖由容器注入。
但这不等于中介者模式。IoC 主要解决对象创建和依赖装配问题;中介者模式主要解决多个对象之间运行时交互协调问题。
所以更准确的说法是:Spring IoC 降低对象创建和装配耦合,但不是典型中介者模式。
三、Spring 事件机制更接近观察者
Spring 的 ApplicationEventPublisher 可以发布事件,监听器通过 @EventListener 接收事件。
applicationEventPublisher.publishEvent(new OrderCreatedEvent(orderId));
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 发送通知、发优惠券等
}
这个机制更像观察者或发布订阅:
- 发布者不关心谁监听;
- 监听者收到事件后自己处理;
- 重点是事件通知,而不是中心协调所有对象。
如果事件中心只做分发,它更偏观察者。如果事件中心写了大量业务路由和协调规则,才可能带有中介者味道。
四、事件总线为什么有中介者思想
事件总线的作用是让模块不直接互调:
OrderModule -> EventBus -> CouponListener
-> NotifyListener
-> StatisticsListener
模块之间不互相依赖,而是通过事件总线通信。
这和中介者模式都在减少直接依赖。
但事件总线通常更通用,偏消息分发;中介者通常更具体,知道一组对象之间的协作规则。
可以这样区分:
- 事件总线:我只负责把事件交给订阅者;
- 中介者:我知道对象之间的协作关系,并决定谁该做什么。
五、业务协调服务更像中介者
在业务代码中,一个 OrderCoordinator 可能负责:
- 调用库存锁定;
- 调用优惠券核销;
- 调用支付;
- 调用通知;
- 处理失败补偿。
这种协调服务就更接近中介者思想。
不过大型业务流程可能还需要:
- 事务控制;
- 分布式一致性;
- 状态机;
- 消息队列;
- 失败重试。
这些已经超出传统中介者模式本身。面试时说“体现中介者思想”会比直接说“这就是中介者模式”更准确。
六、常见误区与追问
Spring 事件和 EventBus 体现“通过中心转交消息”的思想,但更接近观察者或事件总线,不应机械等同于 GoF 中介者。Spring 默认的 SimpleApplicationEventMulticaster 若未配置执行器,监听器通常在发布线程同步执行;配置异步后,事务和异常传播语义会变化。中介者还常显式知道多个同事并协调流程。
| 检查维度 | 判定依据 |
|---|---|
| Spring 事件总线 | 发布者不知道订阅者,一对多通知 |
| 经典 Mediator | 集中掌握并协调同事交互 |
Publisher -> EventMulticaster -> Listener1..N
易错点:有“中心”不等于中介者;要看中心是在广播事件还是编排对象协作。
- 误区:Spring 事件默认就是异步。 默认常为同步调用,只有配置任务执行器等机制后才异步。
- 追问:监听器异常会怎样? 同步模式可能传播回发布者;异步模式需单独处理和观测。
- 误区:事件总线一定降低业务耦合。 事件契约、顺序和隐式订阅过多会形成难追踪的时间耦合。
- 追问:事务提交后再处理怎么做? 可使用
@TransactionalEventListener并选择合适事务阶段。 - 追问:何时更像中介者? 中心组件显式协调多个参与者并决定后续动作,而非单纯广播。
七、加强记忆
Spring IoC 主要管对象创建和依赖装配,不是典型中介者;Spring 事件机制更接近观察者/发布订阅;事件总线和业务协调服务可以体现中介者思想。判断关键是看它是否承担“多个对象之间协作规则的集中协调”,而不是只看有没有一个中心对象。