Browse Source

增加了spring核心学习第17章:Spring事件

seamew 2 years ago
parent
commit
476a12c3a8

+ 260 - 0
后端/Spring/spring源码学习/spring核心编程思想/17、Spring事件.md

@@ -0,0 +1,260 @@
+## 第十七章:Spring事件
+
+### Java事件/监听器编程模型
+
+- 设计模式-观察者模式扩展
+  - 可观者对象(消息发送者)- `java.util.Observable`
+  - 观察者 - `java.util.Observer`
+- 标准化接口
+  - 事件对象 - `java.util.EventObject`
+  - 事件监听器 - `java.util.EventListener`
+
+### 面向接口的事件/监听器设计模式
+
+事件/监听器场景举例
+
+| Java 技术规范   | 事件接口                                | 监听器接口                                 |
+| --------------- | --------------------------------------- | ------------------------------------------ |
+| JavaBeans       | `java.beans.PropertyChangeEvent`        | `java.beans.PropertyChangeListener`        |
+| Java AWT        | `java.awt.event.MouseEvent`             | `java.awt.event.MouseListener`             |
+| Java Swing      | `javax.swing.event.MenuEvent`           | `javax.swing.event.MenuListener`           |
+| Java Preference | `java.util.prefs.PreferenceChangeEvent` | `java.util.prefs.PreferenceChangeListener` |
+
+### 面向注解的事件/监听器设计模式
+
+事件/监听器注解场景举例
+
+| Java 技术规范 | 事件注解                         | 监听器注解                              |
+| ------------- | -------------------------------- | --------------------------------------- |
+| Servlet 3.0+  |                                  | `@javax.servlet.annotation.WebListener` |
+| JPA 1.0+      | `@javax.persistence.PostPersist` |                                         |
+| Java Common   | `@PostConstruct`                 |                                         |
+| EJB 3.0+      | `@javax.ejb.PrePassivate`        |                                         |
+| JSF 2.0+      | `@javax.faces.event.ListenerFor` |                                         |
+
+### Spring 标准事件 - ApplicationEvent
+
+- `org.springframework.context.ApplicationEvent`
+
+- Java 标准事件java.util.EventObject
+
+   
+
+  扩展
+  
+  - 扩展特性:事件发生时间戳
+
+- Spring 应用上下文ApplicationEvent
+
+   
+
+  扩展 -ApplicationContextEvent
+  
+  - `org.springframework.context.event.ApplicationContextEvent`
+  - Spring 应用上下文(ApplicationContext)作为事件源
+  - 具体实现:
+    - `org.springframework.context.event.ContextClosedEvent`
+    - `org.springframework.context.event.ContextRefreshedEvent`
+    - `org.springframework.context.event.ContextStartedEvent`
+    - `org.springframework.context.event.ContextStoppedEvent`
+
+![img](assets/o_201025065102ContextStoppedEvent-16667064887562.png)
+
+### 基于接口的 Spring 事件监听器
+
+Java 标准事件监听器 `java.util.EventListener` 扩展
+
+- 扩展接口 - `org.springframework.context.ApplicationListener`
+- 设计特点:单一类型事件处理
+- 处理方法:`onApplicationEvent(ApplicationEvent)`
+- 事件类型:`org.springframework.context.ApplicationEvent`
+
+### 基于注解的 Spring 事件监听器
+
+Spring 注解 - `@org.springframework.context.event.EventListener`
+
+| 特性                 | 说明                                         |
+| -------------------- | -------------------------------------------- |
+| 设计特点             | 支持多 `ApplicationEvent` 类型,无需接口约束 |
+| 注解目标             | 方法                                         |
+| 是否支持异步执行     | 支持                                         |
+| 是否支持泛型类型事件 | 支持                                         |
+| 是指支持顺序控制     | 支持,配合 `@Order` 注解控制                 |
+
+### 注册 Spring ApplicationListener
+
+- 基于 Spring 接口:向 Spring 应用上下文注册事件
+  - `ApplicationListener` 作为 Spring Bean 注册
+  - 通过 `ConfigurableApplicationContext#addApplicationListener` API 注册
+- 基于 Spring 注解:`@org.springframework.context.event.EventListener`
+
+### Spring事件发布器
+
+- 方法一:通过 ApplicationEventPublisher
+
+   
+
+  发布 Spring 事件
+  
+  - 获取 ApplicationEventPublisher
+    - 依赖注入
+  
+- 方法二:通过 ApplicationEventMulticaster
+
+   
+
+  发布 Spring 事件
+  
+  - 获取 ApplicationEventMulticaster
+
+    - 依赖注入
+- 依赖查找
+
+### Spring层次性上下文事件传播
+
+- 发生说明
+  - 当 Spring 应用出现多层次 Spring 应用上下文(ApplicationContext)时,如 Spring WebMVC、Spring Boot 或 Spring Cloud 场景下,由子 `ApplicationContext` 发起 Spring 事件可能会传递到其 Parent `ApplicationContext`(直到 Root)的过程
+- 如何避免
+  - 定位 Spring 事件源(ApplicationContext)进行过滤处理
+
+### Spring内建事件
+
+`ApplicationContextEvent` 派生事件
+
+- `ContextRefreshedEvent` :Spring 应用上下文就绪事件
+- `ContextStartedEvent` :Spring 应用上下文启动事件
+- `ContextStoppedEvent` :Spring 应用上下文停止事件
+- `ContextClosedEvent` :Spring 应用上下文关闭事件
+
+### Spring 4.2 Payload 事件
+
+Spring Payload 事件 - `org.springframework.context.PayloadApplicationEvent`
+
+- 使用场景:简化 Spring 事件发送,关注事件源主体
+- 发送方法
+  - `ApplicationEventPublisher#publishEvent(java.lang.Object)`
+
+### 自定义 Spring 事件
+
+1. 扩展 `org.springframework.context.ApplicationEvent`
+2. 实现 `org.springframework.context.ApplicationListener`
+3. 将 `org.springframework.context.ApplicationListener` 注册到容器内
+
+### 依赖注入 ApplicationEventPublisher
+
+- 通过 `ApplicationEventPublisherAware` 回调接口
+- 通过 `@Autowired ApplicationEventPublisher`
+
+### 依赖查找 ApplicationEventMulticaster
+
+- 查找条件
+  - Bean 名称:`applicationEventMulticaster`
+  - Bean 类型:`org.springframework.context.event.ApplicationEventMulticaster`
+
+```scss
+AbstractApplicationContext#earlyApplicationEvents 在 prepareRefresh() 中从 null 被赋值,在 registerListeners() 的最后,重新被赋值为 null,并进行了早期事件的发布,
+因为可能存在一个 Bean 同时实现 BeanPostProcessor 和 ApplicationEventPublisherAware,并在 ApplicationEventPublisherAware#setApplicationEventPublisher 方法中发送事件
+因为实现了 BeanPostProcessor,所以这个 Bean 在 registerBeanPostProcessors(beanFactory); 这个方法中初始化,而此时 initApplicationEventMulticaster(); 还没有执行,所以 AbstractApplicationContext#applicationEventMulticaster 为空,无法发布事件,所以先将事件保存在 AbstractApplicationContext#earlyApplicationEvents 中
+```
+
+### ApplicationEventPublisher 底层实现
+
+- 接口:org.springframework.context.event.ApplicationEventMulticaster
+
+  - 抽象类:org.springframework.context.event.AbstractApplicationEventMulticaster
+  
+    - 实现类:`org.springframework.context.event.SimpleApplicationEventMulticaster`
+
+### 同步和异步 Spring 事件广播
+
+- 基于实现类 -org.springframework.context.event.SimpleApplicationEventMulticaster
+
+  - 模式切换:setTaskExecutor(java.util.concurrent.Executor)
+
+     
+    
+    方法
+
+    - 默认模式:同步
+    - 异步模式:如 `java.util.concurrent.ThreadPoolExecutor`
+    
+  - 设计缺陷:不是基于接口契约编程,实现依赖于类本身
+  
+- 基于注解 -@org.springframework.context.event.EventListener
+
+  - 模式切换
+    - 默认模式:同步
+    - 异步模式:标注 `@org.springframework.scheduling.annotation.Async`
+  - 实现限制:无法直接实现同步/异步动态切换
+
+区别:
+
+- 使用 `SimpleApplicationEventMulticaster#setTaskExecutor` 的影响是全局的,使用 `@Async` 是局部的
+- 使用 `SimpleApplicationEventMulticaster#setTaskExecutor` 需要手动关闭线程池,使用 `@Async` 不需要
+
+### Spring 4.1 事件异常处理
+
+- Spring 3.0 错误处理接口 - `org.springframework.util.ErrorHandler`
+- 使用场景
+  - Spring 事件(Events)
+  - `SimpleApplicationEventMulticaster` Spring 4.1 开始支持
+  - Spring 本地调度(Scheduling)
+    - `org.springframework.scheduling.concurrent.ConcurrentTaskScheduler`
+    - `org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler`
+
+### Spring 事件/监听器实现原理
+
+- 核心类 -org.springframework.context.event.SimpleApplicationEventMulticaster
+
+  - 设计模式:观察者模式扩展
+
+    - 被观察者 -org.springframework.context.ApplicationListener
+  
+      - API 添加
+      - 依赖查找
+      
+    - 通知对象 - `org.springframework.context.ApplicationEvent`
+    
+  - 执行模式:同步/异步
+  
+  - 异常处理:`org.springframework.util.ErrorHandler`
+  
+  - 泛型处理:`org.springframework.core.ResolvableType`
+
+### 课外资料
+
+#### Spring Boot 事件
+
+| 事件类型                            | 发生时机                                |
+| ----------------------------------- | --------------------------------------- |
+| ApplicationStartingEvent            | 当 Spring Boot 应用已启动时             |
+| ApplicationStartedEvent             | 当 Spring Boot 应用已启动时             |
+| ApplicationEnvironmentPreparedEvent | 当 Spring Boot Environment 实例已准备时 |
+| ApplicationPreparedEvent            | 当 Spring Boot 应用预备时               |
+| ApplicationReadyEvent               | 当 Spring Boot 应用完全可用时           |
+| ApplicationFailedEvent              | 当 Spring Boot 应用启动失败时           |
+
+#### Spring Cloud 事件
+
+| 事件类型                   | 发生时机                              |
+| -------------------------- | ------------------------------------- |
+| EnvironmentChangeEvent     | 当 Environment 示例配置属性发生变化时 |
+| HeartbeatEvent             | 当 Discoveryclient 客户端发送心跳时   |
+| InstancePreRegisteredEvent | 当服务实例注册前                      |
+| InstanceRegisteredEvent    | 当服务实例注册后                      |
+| RefreshEvent               | 当 RefreshEndpoint 被调用时           |
+| RefreshScopeRefreshedEvent | 当 Refresh Scope Bean 刷新后          |
+
+### 面试题
+
+#### Spring 事件核心接口/组件?
+
+- Spring 事件 - `org.springframework.context.ApplicationEvent`
+- Spring 事件监听器 - `org.springframework.context.ApplicationListener`
+- Spring 事件发布器 - `org.springframework.context.ApplicationEventPublisher`
+- Spring 事件广播器 - `org.springframework.context.event.ApplicationEventMulticaster`
+
+#### Spring 同步和异步事件处理的使用场景?
+
+- Spring 同步事件 - 绝大多数 Spring 使用场景,如 `ContextRefreshedEvent`
+- Spring 异步事件 - 主要 `@EventListener` 与 `@Async` 配合,实现异步处理,不阻塞主线程,比如长时间的数据计算任务等。不要轻易调整 `SimpleApplicationEventMulticaster` 中关联的 `taskExecutor` 对象,除非使用者非常了解 Spring 事件机制,否则容易出现异常行为。

BIN
后端/Spring/spring源码学习/spring核心编程思想/assets/o_201025065102ContextStoppedEvent-16667064887562.png


BIN
后端/Spring/spring源码学习/spring核心编程思想/assets/o_201025065102ContextStoppedEvent.png