0%
这是一片思考的空间 -- arthinking
Spring 重构&代码整洁之道 软件设计 JVM 并发编程 数据结构与算法 分布式 存储 网络 微服务 设计模式
Java技术栈 - 涉及Java技术体系

Spring事件驱动模型

关于事件驱动模型和观察者模型相关内容:事件驱动模型与观察者模式

1、Spring事件驱动模型

image-20191113082055722

如上图:

  • ApplicationListener:Spring事件驱动中的监听器基类接口,也即是观察者,事件消费者的基类接口;通过实现onApplicationEvent方法实现事件监听逻辑;
  • ApplicationEventPublisher:定义了事件的发布接口,即事件源,事件生产者,ApplicationContext类继承类该接口;这里只定义了事件发布规范,具体的实现交由ApplicationEventMulticaster广播发布器的multicastEvent方法来实现。
  • ApplicationEvent:事件对象,Spring事件驱动模型的对象源。其中的source属性通常用来携带事件源;所有需要使用事件驱动模型的事件都可以继承此类。

2、Spring中相关事件类

Spring中的事件对象是ApplicationEvent,该类为Spring事件模型中用于扩展的事件对象,对象中的source属性用来存储事件源,监听器拿到事件对象和事件源之后,对事件作出处理和响应。Spring中部分ApplicationEvent类如下:

image-20191113084132894

3、Spring事件模型执行原理

3.1、事件发布器的初始化

  • ApplicationContext中引用了ApplicationEventMulticaster类,该类可以自定义,如需自定义,在定义bean的时候需要把id设置为:applicationEventMulticaster,才能将自定义的事件发布器注入,原因是AbstractApplicationContext类代码中定义了这个bean id名称:

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";
      ...

      // 优先尝试获取自定义的时间发布器,找不到,则创建一个默认的SimpleApplicationEventMulticaster事件发布器
      protected void initApplicationEventMulticaster() {
      ConfigurableListableBeanFactory beanFactory = getBeanFactory();
      if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
      this.applicationEventMulticaster =
      beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
      if (logger.isTraceEnabled()) {
      logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
      }
      }
      else {
      this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
      beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
      if (logger.isTraceEnabled()) {
      logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
      "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
      }
      }
      }

3.2、事件的发布

事件发布的时候,调用AbstractApplicationContextpublishEvent(Object event, @Nullable ResolvableType eventType)方法,该方法:

  • 将事件转换为ApplicationEvent类型,如果原来不是ApplicationEvent的,则包装为PayloadApplicationEvent类型对象;

  • 调用getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType)发布事件;

  • 如果有父容器,则调用父容器的publishEvent方法;

  • getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType)通过eventType检索到对应的监听器,进行后续处理:

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      @Override
      public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
      ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
      // 判断有没有对applicationEventMulticater的taskExecutor进行赋值,有则使用线程池中的线程进行执行invokeListener
      Executor executor = getTaskExecutor();
      for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      if (executor != null) {
      executor.execute(() -> invokeListener(listener, event));
      }
      else {
      invokeListener(listener, event);
      }
      }
      }

3.3、事件的处理

上面invokeListener方法中的会调用监听器的onApplicationEvent方法执行事件的处理。

References

深入分析Spring事件驱动模型

欢迎关注我的其它发布渠道

订阅IT宅
内功修炼
Java技术栈
Java架构杂谈是IT宅精品文章公众号,欢迎订阅:
📄 网络基础知识:两万字长文50+张趣图带你领悟网络编程的内功心法 📄 HTTP发展史:三万长文50+趣图带你领悟web编程的内功心法 📄 HTTP/1.1:可扩展,可靠性,请求应答,无状态,明文传输 📄 HTTP/1.1报文详解:Method,URI,URL,消息头,消息体,状态行 📄 HTTP常用请求头大揭秘 📄 HTTPS:网络安全攻坚战 📄 HTTP/2:网络安全传输的快车道 📄 HTTP/3:让传输效率再一次起飞 📄 高性能网络编程:图解Socket核心内幕以及五大IO模型 📄 高性能网络编程:三分钟短文快速了解信号驱动式IO 📄 高性能网络编程:彻底弄懂IO复用 - IO处理杀手锏,带您深入了解select,poll,epoll 📄 高性能网络编程:异步IO:新时代的IO处理利器 📄 高性能网络编程:网络编程范式 - 高性能服务器就这么回事 📄 高性能网络编程:性能追击 - 万字长文30+图揭秘8大主流服务器程序线程模型
📄 Java内存模型:如果有人给你撕逼Java内存模型,就把这些问题甩给他 📄 一文带你彻底理解同步和锁的本质(干货) 📄 AQS与并发包中锁的通用实现 📄 ReentrantLock介绍与使用 📄 ReentrantReadWriteLock介绍与使用 📄 ReentrantLock的Condition原理解析 📄 如何优雅的中断线程 📄 如何优雅的挂起线程 📄 图解几个好玩的并发辅助工具类 📄 图解BlockingQueue阻塞队列
📄 消息队列那么多,为什么建议深入了解下RabbitMQ? 📄 高并发异步解耦利器:RocketMQ究竟强在哪里? 📄 Kafka必知必会18问:30+图带您看透Kafka
📄 洞悉MySQL底层架构:游走在缓冲与磁盘之间 📄 SQL运行内幕:从执行原理看调优的本质 📄 洞悉Redis技术内幕:缓存,数据结构,并发,集群与算法