一、觀察者模式場景
1.1 什么是觀察者模式?
觀察者模式(Observer Pattern)觀察者模式是一種行為型設計模式,用于定義一種一對多的依賴關系,當對象的狀態發生變化時,所有依賴于它的對象都會自動收到通知并更新。
核心思想觀察者模式實現了對象之間的解耦:被觀察者(Subject)專注于自身狀態的管理,而觀察者(Observer)專注于對狀態變化的響應,二者通過通知機制進行交互
1.2 傳統開發模式的三大死穴
強耦合陷阱:訂單狀態變更需要手動調用10+通知服務(郵件/SMS/物流…)
擴展噩夢:新增通知渠道必須修改核心業務代碼(違反OCP原則)
性能瓶頸:同步調用鏈導致接口響應時間突破2秒紅線
1.3 觀察者模式的破局之道
事件驅動架構:業務邏輯與事件處理物理隔離
動態擴展能力:新增觀察者零侵入核心系統
異步削峰:實測QPS提升300%(訂單支付場景)
1.4 優點
解耦:被觀察者和觀察者之間的耦合度低,便于擴展。
動態聯動:可以動態添加、移除觀察者,靈活性強。
符合開閉原則:被觀察者的狀態變化通知機制對擴展開放,對修改關閉。
1.5 缺點
性能問題:觀察者過多時,通知機制可能導致性能開銷。
復雜性增加:過多的觀察者與被觀察者關系可能增加系統的復雜性。
可能產生循環依賴:若觀察者與被觀察者相互依賴,可能導致循環調用。
1.6 應用場景
事件驅動模型:如 UI 事件監聽器(按鈕點擊等)。
發布-訂閱機制:消息隊列、事件總線等。
狀態同步:某一對象的狀態變化需要通知多個依賴對象時。
二、技術方案設計
2.1 架構演進對比
2.2 核心組件設計
[事件源] --發布--> [EventBus] --通知--> [觀察者集群]↑ ↖[事件對象] [線程池分發]
三、Java原生實現
3.1 基于JDK的經典實現
// 支付成功事件定義
public class PaymentSuccessEvent extends EventObject {private final String orderId;private final BigDecimal amount;public PaymentSuccessEvent(Object source, String orderId, BigDecimal amount) {super(source);this.orderId = orderId;this.amount = amount;}
}// 支付服務(事件源)
public class PaymentService {private final List<EventListener> listeners = new CopyOnWriteArrayList<>();public void addListener(EventListener listener) {listeners.add(listener);}public void pay(String orderId, BigDecimal amount) {// 支付核心邏輯...notifyListeners(new PaymentSuccessEvent(this, orderId, amount));}private void notifyListeners(PaymentSuccessEvent event) {listeners.forEach(listener -> listener.onEvent(event));}
}// 郵件通知觀察者
public class EmailNotifier implements EventListener {@Overridepublic void onEvent(EventObject event) {if (event instanceof PaymentSuccessEvent) {PaymentSuccessEvent e = (PaymentSuccessEvent) event;sendEmail(e.getOrderId(), e.getAmount());}}
}
3.2 Java9+改進方案
// 使用Flow API實現響應式流
public class PaymentPublisher implements Flow.Publisher<PaymentEvent> {private final Executor executor = ForkJoinPool.commonPool();private final List<Flow.Subscriber<? super PaymentEvent>> subscribers = new CopyOnWriteArrayList<>();@Overridepublic void subscribe(Flow.Subscriber<? super PaymentEvent> subscriber) {subscribers.add(subscriber);subscriber.onSubscribe(new PaymentSubscription(subscriber));}private class PaymentSubscription implements Flow.Subscription {private final Flow.Subscriber<? super PaymentEvent> subscriber;PaymentSubscription(Flow.Subscriber<? super PaymentEvent> subscriber) {this.subscriber = subscriber;}@Overridepublic void request(long n) {// 背壓處理}@Overridepublic void cancel() {subscribers.remove(subscriber);}}
}
四、Spring生態進階實現
4.1 基于ApplicationEvent
// 配置中心變更事件
public class ConfigUpdateEvent extends ApplicationEvent {private final String configKey;private final String newValue;public ConfigUpdateEvent(Object source, String configKey, String newValue) {super(source);this.configKey = configKey;this.newValue = newValue;}
}// 動態配置觀察者
@Component
public class ConfigRefreshListener {@EventListener@Asyncpublic void handleConfigUpdate(ConfigUpdateEvent event) {refreshConfigCache(event.getConfigKey(), event.getNewValue());notifyAllServers(event);}
}// 事件發布
@Service
public class ConfigService {@Autowiredprivate ApplicationEventPublisher eventPublisher;public void updateConfig(String key, String value) {// 更新數據庫eventPublisher.publishEvent(new ConfigUpdateEvent(this, key, value));}
}
4.2 注解驅動增強
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BusinessEventListener {String[] keys() default {};EventMode mode() default EventMode.ASYNC;
}// AOP切面處理
@Aspect
@Component
public class EventListenerAspect {@Around("@annotation(listener)")public Object processEvent(ProceedingJoinPoint pjp, BusinessEventListener listener) {EventObject event = (EventObject) pjp.getArgs()[0];if (shouldHandle(event, listener.keys())) {return switch (listener.mode()) {case ASYNC -> CompletableFuture.runAsync(() -> proceed(pjp));case TRANSACTIONAL -> executeInTransaction(pjp);default -> proceed(pjp);};}return null;}
}
五、生產級優化方案
5.1 性能優化策略
5.2 可靠性保障
// 事件持久化方案
public class PersistentEventBus {private final EventStoreRepository eventStore;@Transactional(propagation = Propagation.REQUIRES_NEW)public void publishWithPersistence(DomainEvent event) {eventStore.save(event);realPublish(event);}// 定時補償任務@Scheduled(fixedRate = 60000)public void retryFailedEvents() {eventStore.findFailedEvents().forEach(event -> {try {realPublish(event);event.markAsSent();} catch (Exception e) {event.recordRetry();}});}
}
六、經典應用場景
6.1 電商訂單系統
支付成功事件 → 庫存扣減/物流觸發/積分發放使用「發布-確認-補償」機制保證最終一致性
6.2 微服務配置中心
配置變更事件 → 所有服務實例動態刷新結合Spring Cloud Bus實現集群通知
6.3 物聯網數據采集
設備狀態事件 → 實時監控/預警分析/大屏展示采用MQTT協議實現百萬級設備連接
七、避坑指南
7.1 常見問題排查
內存泄漏:
檢查觀察者是否及時取消注冊
使用WeakReference包裝監聽器
事件丟失:
增加本地事件持久化層
實現至少一次投遞語義
循環觸發:
在事件對象中添加traceId
設置最大傳播深度閾值
7.2 生產注意事項
事件版本控制:使用Avro Schema管理事件格式
監控埋點:統計事件處理耗時/成功率
熔斷降級:Hystrix隔離異常觀察者