乐趣区

关于java:spring-50x源码学习系列十-观察者设计模式与Spring-事件驱动模型

前言

  • 上篇博客 spring 5.0.x 源码学习系列九: FactoryBean 和 BeanFactory 次要介绍了 spring 中的两个非凡的 bean, FactoryBeanBeanFactory。本次,咱们将开始介绍下 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);
           }
       }
    1. 新建事件监听器。

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

         // 拿到 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.
退出移动版