面试知识库
基础

观察者模式#

一句话答案#

一对多依赖关系,主题状态改变时通知所有观察者;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);
}
java

Spring Event 事件机制(观察者模式的实现):

Spring 提供了完整的事件发布-订阅机制:

Spring Event 的底层实现:

  1. ApplicationEventPublisher 内部维护一个 ApplicationEventMulticaster
  2. Multicaster 持有所有 ApplicationListener 的列表
  3. 发布事件时,遍历匹配的 Listener 依次调用 onApplicationEvent()
  4. @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 异常影响发布者——默认同步会影响