一、观察者模式场景
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 核心组件设计
java
[事件源] --发布--> [EventBus] --通知--> [观察者集群]
↑ ↖
[事件对象] [线程池分发]
三、Java原生实现
3.1 基于JDK的经典实现
java
// 支付成功事件定义
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 {
@Override
public void onEvent(EventObject event) {
if (event instanceof PaymentSuccessEvent) {
PaymentSuccessEvent e = (PaymentSuccessEvent) event;
sendEmail(e.getOrderId(), e.getAmount());
}
}
}
3.2 Java9+改进方案
java
// 使用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<>();
@Override
public 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;
}
@Override
public void request(long n) {
// 背压处理
}
@Override
public void cancel() {
subscribers.remove(subscriber);
}
}
}
四、Spring生态进阶实现
4.1 基于ApplicationEvent
java
// 配置中心变更事件
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
@Async
public void handleConfigUpdate(ConfigUpdateEvent event) {
refreshConfigCache(event.getConfigKey(), event.getNewValue());
notifyAllServers(event);
}
}
// 事件发布
@Service
public class ConfigService {
@Autowired
private ApplicationEventPublisher eventPublisher;
public void updateConfig(String key, String value) {
// 更新数据库
eventPublisher.publishEvent(new ConfigUpdateEvent(this, key, value));
}
}
4.2 注解驱动增强
java
@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 可靠性保障
java
// 事件持久化方案
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 电商订单系统
java
支付成功事件 → 库存扣减/物流触发/积分发放
使用「发布-确认-补偿」机制保证最终一致性
6.2 微服务配置中心
java
配置变更事件 → 所有服务实例动态刷新
结合Spring Cloud Bus实现集群通知
6.3 物联网数据采集
java
设备状态事件 → 实时监控/预警分析/大屏展示
采用MQTT协议实现百万级设备连接
七、避坑指南
7.1 常见问题排查
内存泄漏:
检查观察者是否及时取消注册
使用WeakReference包装监听器
事件丢失:
增加本地事件持久化层
实现至少一次投递语义
循环触发:
在事件对象中添加traceId
设置最大传播深度阈值
7.2 生产注意事项
事件版本控制:使用Avro Schema管理事件格式
监控埋点:统计事件处理耗时/成功率
熔断降级:Hystrix隔离异常观察者