前言
- 上篇博客 spring 5.0.x 源码学习系列九: FactoryBean 和 BeanFactory 次要介绍了 spring 中的两个非凡的 bean, FactoryBean和 BeanFactory。本次,咱们将开始介绍下 spring 的事件驱动模型以及它应用的设计模式: 观察者设计模式。
一、观察者模式
1.1 依据一个案例实现一个观察者设计模式
- 假如有这么一个场景,小黄和小杨一起在看电影,当电影播放到 精彩 的剧情时,小黄小杨别离会有不同的行为表现。小黄会睡觉,小杨会哭泣。上面咱们将应用代码来模拟出这个案例。
1.1.1 版本 1
- Application.java 入口类
- Huang.java 小黄实体类
- Yang.java 小杨实体类
- Movie.java 电影类
- 运行后果
-
小结:
- 应用上述的形式实现了案例的需要,但有如下毛病
- 观察者须要全程观看电影,占用观察者大量工夫
- 当电影播放到精彩局部的时候本人来被动告诉本人要做些事件了。
1.1.2 版本二
-
修复了版本一的问题:
- 由电影来告诉观察者,省去观察者须要全程观看电影的毛病,由电影来告诉观察者该做一些事件了
- Application.java
- Huang.java
- Yang.java
- Movie.java
- 运行后果
-
小结,版本二的观察者模式具备如下毛病:
- 观察者的行为动作不对立,被观察者代码保护难度大
- 扩展性低,若观察者须要减少,则须要手动在被察看中增加观察者的援用,反复工作多
1.1.3 版本 3
-
此版本修复了版本 2 的毛病:
- 观察者行为动作不对立
- 扩展性低
- MovieObserver.java
- Application.java
- Huang.java
- Movie.java
- Yang.java
- 运行后果
-
小结
- 版本 3 是观察者模式的根本模型,然而它并没有形象出事件的概念。其实也形象进去了。MovieObserver相当于事件的监听者,Movie播放精彩局部的动作是一个事件。notifyObservers相当于公布事件。
1.1.4 版本 4
- 此版本基于版本 3 做了些批改, 将事件、监听者、公布事件的概念增加了进去
- MovieEvent.java
- MovieListener.java
- Application.java
- Huang.java
- Movie.java
- Yang.java
- 运行后果
-
小结
- 版本 4 将事件的概念形象了进去,会依据公布不同的事件响应不同的行为
- 在此版本中,一共定义了两种类型的事件 感人类型事件 , 悲剧类型事件
1.2 观察者设计模式特点
- 被观察者持有观察者的援用
- 耦合性低,被观察者在
特定工夫
公布特定事件
,观察者具体的行为动作由观察者本人决定 - 提供新增和移除观察者 api,可任意扩容观察者数量
二、Spring 事件模型
2.1 spring 事件模型类型
- ApplicationContextEvent
- RequestHandlerEvent
2.2 ApplicationContextEvent 事件触发步骤
-
新建自定义事件源。继承 ApplicationEvent 类, 并重写带参构造方法
public class MyApplicationEvent extends ApplicationEvent { // 带参构造方法中的参数就是能够为事件增加一些参数, 即 // 自定义一些事件 public MyApplicationEvent(Object source) {super(source); } }
-
新建事件监听器。
// 1. 须要增加 @Component 注解, 让监听者作为 spring 的一个 bean // 2. 其次, 要实现 ApplicationListener 接口, 泛型为上述定义的事件源(MyApplicationEvent) @Component public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> { @Override public void onApplicationEvent(MyApplicationEvent event) {System.out.println("监听者," + event); } }
-
获取 spring ApplicationEventPublisher 对象
// 新建了一个 bean 来保护上下文对象 @Component public class ApplicationContextHolder implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {applicationContext = applicationContext;} public static ApplicationContext getApplicationContext() {return applicationContext;} }
-
触发事件
// 拿到 spring 上下文公布事件 // spring 上下文如何拿到?spring 上下文是指实现了 ApplicationContext 接口的类 // 在以 java config 技术开启的 spring 应用程序中, 能够用 AnnotationConfigApplicationContext 的实例, 第三步能够疏忽 // 若是 spring web 应用程序, eg: spring mvc, 则能够新增一个 bean 并实现 ApplicationContextAware 接口, eg: 第三步 ApplicationContextHolder.getApplicationContext().publishEvent(new MyApplicationEvent(new String[] {"1", "2"}))
-
2.3 ApplicationContextEvent 的四种类型总结
类型 | 如何触发 | 触发机会 | spring 上下文初始化后是否能触发 |
---|---|---|---|
ContextRefreshEvent | 公布类型为 ContextRefreshEvent 的事件. | 调用 spring 上下文 refersh 办法 | 是 |
ContextStopEvent | 公布类型为 ContextStopEvent 的事件 | 调用 spring 上下文 stop 办法 | 否 |
ContextStartEvent | 公布类型为 ContextStartEvent 的事件 | 调用 spring 上下文 start 办法 | 否 |
ContextCloseEvent | 公布类型为 ContextCloseEvent 的事件 | 调用 spring 上下文 close 办法 | 否 |
- 上述的触发机会可参考此 url:https://github.com/AvengerEug/observer-csdn/blob/develop/src/main/java/springevent/Entry.java
2.4 RequestHandlerEvent 类型的事件
- 待总结
三、总结
- Spring 事件驱动模型是基于观察者设计模式衍生而来的,jdk 也有自带的观察者设计模式类,别离是 被观察者: Observable,观察者: Observer。但 jdk 自带的观察者设计模式类并没有把事件集成进去,尽管 JDK 中存在事件相干的类,比方 EventObject 类,但仅仅是被利用到了 java swing 编程。
- 本次博客代码仓库地址: https://github.com/AvengerEug/observer-csdn.git
- I am a slow walker, but I never walk backwards.