外观
一句话答案
一对多依赖关系,主题状态改变时通知所有观察者;Spring 的 @EventListener + ApplicationEventPublisher 是观察者实现。
核心要点
观察者模式定义对象间一对多的依赖关系,当一个对象(Subject/主题)状态改变时,所有依赖它的对象(Observer/观察者)都会收到通知并自动更新。
核心角色:
- Subject(主题/被观察者):维护观察者列表,提供注册/移除/通知方法
- Observer(观察者):定义
update()方法,接收主题的通知
java
// 主题接口
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// 观察者接口
public interface Observer {
void update(Object data);
}Spring Event 事件机制(观察者模式的实现):
Spring 提供了完整的事件发布-订阅机制:
java
// 1. 定义事件
public class OrderCreatedEvent extends ApplicationEvent {
private final Order order;
public OrderCreatedEvent(Object source, Order order) {
super(source);
this.order = order;
}
public Order getOrder() { return order; }
}
// 2. 发布事件(Subject 角色)
@Service
public class OrderService {
@Autowired
private ApplicationEventPublisher publisher;
public void createOrder(Order order) {
// 业务逻辑...
publisher.publishEvent(new OrderCreatedEvent(this, order));
}
}
// 3. 监听事件(Observer 角色)
@Component
public class SmsNotificationListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 发送短信通知
}
}
@Component
public class InventoryListener {
@EventListener
public void onOrderCreated(OrderCreatedEvent event) {
// 扣减库存
}
}Spring Event 的底层实现:
ApplicationEventPublisher内部维护一个ApplicationEventMulticasterMulticaster持有所有ApplicationListener的列表- 发布事件时,遍历匹配的 Listener 依次调用
onApplicationEvent() @EventListener注解通过EventListenerMethodProcessor在启动时扫描并注册
同步 vs 异步事件:
- 默认同步:事件处理在发布者的线程中执行
- 异步处理:在监听方法上加
@Async+ 开启@EnableAsync
观察者模式的优缺点:
- 优点:主题和观察者松耦合;支持广播通信;符合开闭原则
- 缺点:观察者过多时通知耗时;循环依赖风险;同步通知可能阻塞
追问与易错
追问方向:
- Spring 事件同步还是异步?
- 发布订阅和观察者区别?
- Spring 事件有什么局限?
易错点:
- ❌ Spring 事件等于 MQ——是进程内的
- ❌ @EventListener 异常影响发布者——默认同步会影响
💡 记忆锚点
微信公众号模式:公众号(Subject)发一篇文章,所有关注者(Observer)同时收到推送。Spring里publishEvent()就是发文章,@EventListener就是关注按钮,默认同步推送、加@Async变异步推送。注意这是进程内广播,跨进程得上MQ。