当前位置: 首页 > article >正文

观察者模式原理详解以及Spring源码如何使用观察者模式?

前言

  首先说明观察者模式,观察者模式,也叫发布-订阅模式,应该是用来处理对象间的一对多依赖关系的。当被观察者的状态变化时,所有依赖它的观察者都会得到通知并自动更新。

  观察者模式的结构,通常包括Subject(主题)和Observer(观察者)两个主要角色。Subject维护一个观察者列表,提供注册和移除的方法,还有通知观察者的方法。Observer则有一个更新方法,当Subject状态变化时被调用。可能还有具体的ConcreteSubject和ConcreteObserver,实现具体的业务逻辑。

  Spring框架中有很多地方用到了观察者模式,特别是事件驱动模型。比如ApplicationEvent和ApplicationListener,用户自定义事件,然后通过ApplicationContext发布事件,监听器会接收到这些事件进行处理。这是典型的观察者模式的应用。

  需要详细说明Spring中的事件机制。ApplicationEvent是所有事件的父类,自定义事件需要继承它。ApplicationListener是观察者接口,实现onApplicationEvent方法来处理事件。ApplicationContext作为事件发布者,有publishEvent方法。当事件发布时,所有注册的监听该事件类型的监听器都会被触发。

  另外,Spring的事件传播机制可能涉及到同步和异步处理。默认是同步的,但可以通过配置实现异步监听,比如使用@Async注解或者配置TaskExecutor。

  还涉及Spring内置的一些事件,比如ContextRefreshedEvent、ContextStartedEvent等,这些事件在容器生命周期不同阶段发布,监听器可以响应这些事件执行相应逻辑。

  在本文中会结合源码分析,ApplicationContext的publishEvent方法内部如何获取监听器,如何调用他们的onApplicationEvent方法。可能涉及到ApplicationEventMulticaster这个类,它负责管理监听器和事件广播。具体实现类SimpleApplicationEventMulticaster,使用线程池支持异步事件处理。

  其中,Spring中的观察者模式与传统观察者模式的区别,比如Spring使用ApplicationContext作为事件发布者,而传统模式可能由Subject直接维护观察者列表。此外,Spring支持基于注解的事件监听,比如@EventListener,简化了监听器的注册和使用。

  学完本篇可以在项目中使用观察者模式,比如通过自定义事件和监听器实现解耦的业务逻辑。比如订单创建后发送邮件通知,可以定义一个OrderCreatedEvent,监听器处理发送邮件的逻辑,这样订单服务和邮件服务就解耦了。

  还需要注意可能的问题,比如监听器的执行顺序,异常处理,异步监听时的线程池配置等。这些都是实际使用中需要考虑的。

  总结来说,回答需要分两部分:观察者模式的原理,包括结构、角色和流程;然后是Spring中的具体实现,结合事件机制和源码分析,说明如何利用ApplicationEvent、ApplicationListener以及相关类来实现观察者模式,并给出实际应用示例。


观察者模式原理详解及 Spring 源码应用分析

一、观察者模式(Observer Pattern)原理

核心思想:定义对象间的一对多依赖关系,当一个对象(被观察者/主题)状态发生改变时,所有依赖它的对象(观察者)会自动收到通知并更新。
别名:发布-订阅模式(Pub-Sub)。

1. 模式结构
角色职责
Subject(主题)维护观察者列表,提供注册、移除和通知观察者的方法。
Observer(观察者)定义更新接口,用于接收主题状态变化的通知。
ConcreteSubject具体主题,实现状态变更逻辑,并在状态变化时通知所有观察者。
ConcreteObserver具体观察者,实现更新逻辑以响应主题状态变化。
2. 类图
+----------------+          +----------------+
|   Subject      |          |   Observer     |
+----------------+          +----------------+
| +attach(Observer)| <------| +update():void |
| +detach(Observer)|        +----------------+
| +notify()       |                  ^
+----------------+                   |
        ^                            |
        |                            |
+----------------+          +------------------+
| ConcreteSubject |          | ConcreteObserver |
+----------------+          +------------------+
| +getState()    |          | +update()        |
| +setState()    |          +------------------+
+----------------+
3. 执行流程
  1. 观察者注册ConcreteObserver 调用 Subject.attach() 注册到主题。
  2. 状态变更触发通知ConcreteSubject 调用 setState() 修改状态后,触发 notify()
  3. 广播通知Subject 遍历观察者列表,调用每个观察者的 update() 方法。

二、Spring 源码中的观察者模式实现

Spring 通过 事件驱动模型 实现观察者模式,核心涉及以下组件:

  • ApplicationEvent:所有事件的基类(如 ContextRefreshedEvent)。
  • ApplicationListener:观察者接口,监听特定事件。
  • ApplicationEventPublisher:主题接口,用于发布事件(由 ApplicationContext 实现)。
  • ApplicationEventMulticaster:事件广播器,管理监听器并分发事件。
1. Spring 事件机制核心流程
1. 定义事件 → 2. 发布事件 → 3. 监听器处理事件
2. 源码解析
(1)事件发布:ApplicationContext.publishEvent()

入口AbstractApplicationContext#publishEvent
流程

public void publishEvent(ApplicationEvent event) {
    getApplicationEventMulticaster().multicastEvent(event); // 广播事件
    // 若父容器存在,递归向上传播事件
    if (this.parent != null) {
        this.parent.publishEvent(event);
    }
}
(2)事件广播:ApplicationEventMulticaster

实现类SimpleApplicationEventMulticaster
关键方法multicastEvent()

public void multicastEvent(ApplicationEvent event) {
    for (ApplicationListener<?> listener : getApplicationListeners(event)) {
        // 判断是否支持异步执行
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute(() -> invokeListener(listener, event));
        } else {
            invokeListener(listener, event); // 同步调用监听器
        }
    }
}

private void invokeListener(ApplicationListener listener, ApplicationEvent event) {
    listener.onApplicationEvent(event); // 触发监听器逻辑
}
(3)监听器注册与匹配
  • 注册:Spring 容器启动时,自动扫描所有实现 ApplicationListener 的 Bean。
  • 匹配规则:通过 supportsEventType() 检查监听器是否支持当前事件类型。

示例GenericApplicationListener 判断事件类型:

public boolean supportsEventType(ResolvableType eventType) {
    return (this.delegate == this || this.delegate.supportsEventType(eventType));
}
3. Spring 内置事件示例
事件类型触发时机
ContextRefreshedEvent容器初始化或刷新完成时(所有 Bean 已加载)。
ContextStartedEvent调用 ConfigurableApplicationContext.start() 时。
ContextStoppedEvent调用 ConfigurableApplicationContext.stop() 时。
RequestHandledEventHTTP 请求处理完成后。

三、Spring 观察者模式的实际应用
1. 自定义事件与监听器

步骤

  1. 定义事件:继承 ApplicationEvent
  2. 定义监听器:实现 ApplicationListener 或使用 @EventListener 注解。
  3. 发布事件:通过 ApplicationContext.publishEvent() 发布。

代码示例

// 1. 自定义事件
public class OrderCreatedEvent extends ApplicationEvent {
    private String orderId;
    public OrderCreatedEvent(Object source, String orderId) {
        super(source);
        this.orderId = orderId;
    }
    public String getOrderId() { return orderId; }
}

// 2. 监听器实现(注解方式)
@Component
public class EmailNotificationListener {
    @EventListener
    public void handleOrderCreatedEvent(OrderCreatedEvent event) {
        System.out.println("发送邮件通知,订单ID: " + event.getOrderId());
    }
}

// 3. 发布事件
@Service
public class OrderService {
    @Autowired
    private ApplicationContext applicationContext;

    public void createOrder(String orderId) {
        // 业务逻辑...
        applicationContext.publishEvent(new OrderCreatedEvent(this, orderId));
    }
}
2. 异步事件处理

配置异步监听器

@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        return Executors.newFixedThreadPool(5);
    }
}

// 使用 @Async 注解异步处理
@Component
public class LoggingListener {
    @Async
    @EventListener
    public void asyncLogOrderEvent(OrderCreatedEvent event) {
        System.out.println("异步记录日志,订单ID: " + event.getOrderId());
    }
}
3. 监听器执行顺序

通过 @Order 注解控制监听器执行顺序:

@EventListener
@Order(1)
public void firstListener(OrderCreatedEvent event) {
    System.out.println("第一个执行");
}

@EventListener
@Order(2)
public void secondListener(OrderCreatedEvent event) {
    System.out.println("第二个执行");
}

四、Spring 观察者模式的设计优势
  1. 解耦业务逻辑
    事件发布者与监听者无需直接交互,例如订单服务不依赖邮件服务。
  2. 扩展性强
    新增监听器只需实现接口或添加注解,无需修改发布者代码。
  3. 支持异步处理
    通过 TaskExecutor 实现异步事件处理,提升系统吞吐量。
  4. 事件传播机制
    支持事件在容器层次结构中向上传播(如父子容器)。

五、总结
  • 观察者模式核心:解耦主题与观察者,通过事件通知机制实现松耦合通信。
  • Spring 实现:基于 ApplicationEventApplicationListenerApplicationEventMulticaster 构建事件驱动模型。
  • 应用场景
    • 业务流程解耦(如订单创建后发送通知、记录日志)。
    • 系统生命周期管理(如容器启动后加载缓存)。
    • 异步任务触发(如消息队列事件处理)。

源码设计亮点

  • 事件类型匹配:通过 ResolvableType 动态解析事件类型,支持泛型事件。
  • 灵活广播策略SimpleApplicationEventMulticaster 支持同步/异步事件分发。
  • 注解驱动简化@EventListener@Async 简化监听器定义与异步配置。

http://www.kler.cn/a/555875.html

相关文章:

  • 【ROS2】卡尔曼滤波学习:概念、数学推导和C++实现方法
  • Python3测试开发面试题2
  • 蓝桥杯试题:串的处理
  • 深度解析Token:从技术原理到商业应用的全栈指南
  • 【Kubernetes】常用命令全解析:从入门到实战(下)
  • JavaEE基础之- Servlet相关
  • 单片机中有FLASH为啥还需要EEROM?
  • 【探商宝】2025年2月科技与商业热点头条:AI竞赛、量子计算与芯片市场新格局
  • OpenAI ChatGPT在心理治疗领域展现超凡同理心,通过图灵测试挑战人类专家
  • Linux内核实时机制7 - 实时改造机理 - 软中断优化下
  • 排序02(数据结构初阶)
  • 【DiffGAD: A Diffusion-based Unsupervised Graph Anomaly Detector】
  • 网页制作05-html,css,javascript初认识のhtml表格的创建
  • 嵌入式之PWM
  • 精选模块-ES6模块
  • 基于51单片机的秒表系统proteus仿真
  • FFmpeg+WebSocket+JsMpeg实时视频流实现方案
  • Windows 图形显示驱动开发-查询 WDDM(3.2) 功能支持和启用
  • springboot整合mybatis-plus【详细版】
  • 数据结构:动态数组vector