高 基础
观察者模式#
一句话答案#
一对多依赖关系,主题状态改变时通知所有观察者;Spring 的 @EventListener + ApplicationEventPublisher 是观察者实现。
核心要点
观察者模式定义对象间一对多的依赖关系,当一个对象(Subject/主题)状态改变时,所有依赖它的对象(Observer/观察者)都会收到通知并自动更新。
核心角色:
- Subject(主题/被观察者):维护观察者列表,提供注册/移除/通知方法
- Observer(观察者):定义
update()方法,接收主题的通知
// 主题接口
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// 观察者接口
public interface Observer {
void update(Object data);
}javaSpring Event 事件机制(观察者模式的实现):
Spring 提供了完整的事件发布-订阅机制:
// 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) {
// 扣减库存
}
}javaSpring Event 的底层实现:
ApplicationEventPublisher内部维护一个ApplicationEventMulticasterMulticaster持有所有ApplicationListener的列表- 发布事件时,遍历匹配的 Listener 依次调用
onApplicationEvent() @EventListener注解通过EventListenerMethodProcessor在启动时扫描并注册
同步 vs 异步事件:
- 默认同步:事件处理在发布者的线程中执行
- 异步处理:在监听方法上加
@Async+ 开启@EnableAsync
观察者模式的优缺点:
- 优点:主题和观察者松耦合;支持广播通信;符合开闭原则
- 缺点:观察者过多时通知耗时;循环依赖风险;同步通知可能阻塞
面试回答(2分钟版)
观察者模式定义的是一对多的依赖关系,当主题对象状态改变时自动通知所有观察者。核心有两个角色:Subject维护观察者列表并负责通知,Observer定义update方法接收通知。在Spring中观察者模式通过事件机制实现:定义一个继承ApplicationEvent的事件类,发布者通过ApplicationEventPublisher.publishEvent()发布事件,监听者用@EventListener注解标记方法即可自动接收。底层原理是ApplicationEventMulticaster维护了所有Listener的列表,发布时遍历匹配的Listener依次调用。默认是同步执行的,也就是说监听方法在发布者线程中跑,如果监听方法抛异常会影响发布者。要异步处理的话在监听方法上加@Async并开启@EnableAsync即可。需要注意的是Spring事件是进程内的广播机制,跨服务通信还是需要用消息队列。
追问与易错
追问方向:
- “Spring 事件同步还是异步?”→ 默认同步执行,监听方法在发布者线程中运行,监听方法抛异常会影响发布者;加 @Async + @EnableAsync 可改为异步执行
- “发布订阅和观察者区别?”→ 观察者模式中 Subject 直接通知 Observer(强耦合);发布订阅模式引入中间层(事件总线/消息代理),发布者和订阅者完全解耦互不感知,Spring Event 介于两者之间
- “Spring 事件有什么局限?”→ 是进程内广播机制,不支持跨服务通信(跨服务需用 MQ);默认同步执行可能阻塞发布者;没有持久化和重试机制,监听失败不会自动重试
易错点:
- ❌ Spring 事件等于 MQ——是进程内的
- ❌ @EventListener 异常影响发布者——默认同步会影响