spring 5.0.x源码学习系列十: 观察者设计模式与Spring 事件驱动模型

前言

一、观察者模式

1.1 根据一个案例实现一个观察者设计模式

  • 假设有这么一个场景,小黄和小杨一起在看电影,当电影播放到精彩的剧情时,小黄小杨分别会有不同的行为表现。小黄会睡觉,小杨会哭泣。下面我们将使用代码来模拟出这个案例。
1.1.1 版本1
  • Application.java入口类
    在这里插入图片描述
  • Huang.java小黄实体类
    在这里插入图片描述
  • Yang.java小杨实体类
    在这里插入图片描述
  • Movie.java电影类
    在这里插入图片描述
  • 运行结果
    在这里插入图片描述
  • 小结:
    • 使用上述的方式实现了案例的需求,但有如下缺点
    1. 观察者需要全程观看电影,占用观察者大量时间
    2. 当电影播放到精彩部分的时候自己来主动通知自己要做些事情了。
1.1.2 版本二
  • 修复了版本一的问题:

    1. 由电影来通知观察者,省去观察者需要全程观看电影的缺点,由电影来通知观察者该做一些事情了
  • Application.java
    在这里插入图片描述

  • Huang.java
    在这里插入图片描述

  • Yang.java
    在这里插入图片描述

  • Movie.java
    在这里插入图片描述

  • 运行结果
    在这里插入图片描述

  • 小结,版本二的观察者模式具有如下缺点:

    1. 观察者的行为动作不统一,被观察者代码维护难度大
    2. 扩展性低,若观察者需要增加,则需要手动在被观察中添加观察者的引用,重复工作多
1.1.3 版本3
  • 此版本修复了版本2的缺点:
    1. 观察者行为动作不统一
    2. 扩展性低
  • MovieObserver.java
    在这里插入图片描述
  • Application.java
    在这里插入图片描述
  • Huang.java
    在这里插入图片描述
  • Movie.java
    在这里插入图片描述
  • Yang.java在这里插入图片描述
  • 运行结果
    在这里插入图片描述
  • 小结
    1. 版本3是观察者模式的基本模型,但是它并没有抽象出事件的概念。其实也抽象出来了。MovieObserver相当于事件的监听者,Movie播放精彩部分的动作是一个事件。notifyObservers相当于发布事件。
1.1.4 版本4
  • 此版本基于版本3做了些修改, 将事件、监听者、发布事件的概念添加了进去

  • MovieEvent.java
    在这里插入图片描述

  • MovieListener.java
    在这里插入图片描述

  • Application.java
    在这里插入图片描述

  • Huang.java
    在这里插入图片描述

  • Movie.java
    在这里插入图片描述

  • Yang.java
    在这里插入图片描述

  • 运行结果
    在这里插入图片描述

  • 小结

    1. 版本4将事件的概念抽象了出来,会根据发布不同的事件响应不同的行为
    2. 在此版本中,一共定义了两种类型的事件感人类型事件, 喜剧类型事件

1.2 观察者设计模式特点

  • 被观察者持有观察者的引用
  • 耦合性低,被观察者在特定时间发布特定事件,观察者具体的行为动作由观察者自己决定
  • 提供新增和移除观察者api,可任意扩容观察者数量

二、Spring 事件模型

2.1 spring事件模型类型

  • ApplicationContextEvent
  • RequestHandlerEvent

2.2 ApplicationContextEvent事件触发步骤

  1. 新建自定义事件源。继承ApplicationEvent类, 并重写带参构造方法

       public class MyApplicationEvent extends ApplicationEvent {
           // 带参构造方法中的参数就是可以为事件添加一些参数, 即
           // 自定义一些事件
           public MyApplicationEvent(Object source) {
               super(source);
           }
       }
    
  2. 新建事件监听器。

       // 1. 需要添加@Component注解, 让监听者作为spring的一个bean
       // 2. 其次, 要实现ApplicationListener接口, 泛型为上述定义的事件源(MyApplicationEvent)
       @Component
       public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
       
           @Override
           public void onApplicationEvent(MyApplicationEvent event) {
               System.out.println("监听者, " + event);
           }
       }
    
  3. 获取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;
           }
       }
    
  4. 触发事件

       // 拿到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方法

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.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值