零维护

 找回密码
 立即注册
快捷导航
搜索
热搜: 活动 交友 discuz
查看: 106|回复: 2

【Spring源码】14. 消息多播器(观察者模式)

[复制链接]

1

主题

1

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2022-9-21 15:45:54 | 显示全部楼层 |阅读模式
本文主要涉及三个方法 initApplicationEventMulticaster()、onRefresh()、registerListeners()
观察者模式

先简单介绍下观察者模式
观察者模式是指当一个行为发生时,一个用户传递信息,另一个用户接收信息并作出相应的处理,行为和接受者之间没有直接的耦合关系(《重学Java设计模式》)
比较常见应用于MQ(Message Queue,消息队列)服务中
分为被观察者观察者

  • 被观察者的对象存在一个集合中,执行不同方法时,调用观察者的方法进行处理
  • 观察者则在看到被观察者的某种行为后执行相应的行为
事件驱动

传统的事件驱动分为被观察者和观察者,而Spring将他们进行了解耦,抽象成了4个概念,分别是:

  • 事件

    • 被观察者具体要执行的动作

  • 监听器(观察者)

    • 可能存在多个
    • 接受不同的事件来做不同的处理工作

  • 多播器

    • 广播事件
    • 将被观察者通知多个观察者这个遍历的操作委托给一个多播器来完成

  • 事件源

    • 调用/执行发布的具体事件动作的发出者

逻辑流程

先捋下逻辑哈@(・●・)@

  • 事件源发布不同的事件
  • 发布事件后,执行多播器的方法来进行事件广播操作,触发具体的监听器
  • 监听器接收到具体的事件后,会验证与自己的逻辑是匹配

    • 匹配:处理
    • 不匹配:不做任何操作

代码执行流程


  • 准备多个事件
  • 初始化多播器(需要包含一个存放监听器的集合)
  • 准备监听器
  • 将准备好的监听器注册到多播器中(放到多播器的几何中,方以便后续多播器进行广播通知)
  • 事件发布,触发多播器
消息多播器相关方法详解

主要涉及refresh()方法中的initApplicationEventMulticaster()、onRefresh()、registerListeners()三个方法,如下图


初始化事件监听多路广播器、initApplicationEventMulticaster()


这个方法主要执行了两大步骤:

  • 获取当前Bean工厂,一般是DefaultListableBeanFactory
  • 判断当前bean工厂里是否包含BEAN_NAME为applicationEventMulticaster(自定义事件监听多播器)的Bean

    • 有的话获取
    • 没有的话,设置默认的(SimpleApplicationEventMulticaster)

然后,我们再继续看
SimpleApplicationEventMulticaster是啥么




Simple implementation of the {@link ApplicationEventMulticaster} interface.
翻译下:对{@link ApplicationEventMulticaster}接口的简单实现
也就是SimpleApplicationEventMulticaster实现叻ApplicationEventMulticaster,但我们看到的源码是SimpleApplicationEventMulticaster继承了AbstractApplicationEventMulticaster
然然后,我们再继续看
AbstractApplicationEventMulticaster是啥么


Abstract implementation of the {@link ApplicationEventMulticaster} interface, providing the basic listener registration facility.
{@link ApplicationEventMulticaster}接口的抽象实现,提供基本的监听器注册功能
所以他们之间的关系是:
AbstractApplicationEventMulticaster实现了ApplicationEventMulticaster,然后SimpleApplicationEventMulticaster继承了AbstractApplicationEventMulticaster
AbstractApplicationEventMulticaster这个抽象类里有两个关键的方法addApplicationListener()和addApplicationListenerBean()(在后面调用registerListeners()方法时会使用到,将不同方式获取的监听器分别放入相应的集合中)


初始化其他bean、onRefresh()
这个是留给子类做扩展的,里面啥都木得(˶‾᷄ ⁻̫ ‾᷅˵)


注册bean到消息广播器中、registerListeners()


此方法主要分为三个内容:

  • 遍历应用程序中存在的监听器集合,并将对应的监听器添加到监听器的多路广播器中(此处添加的是对象)
  • 从容器中获取所有实现了ApplicationListener接口的BeanDefinition的BeanName,放入集合ApplicationListenerBeans中(此处添加的是名称,这种方式后面一般会通过beanFactory.getBean(listenerBeanName, ApplicationListener.class获取到其对象))
  • 发布监听器集合(早期的)


将给定的事件发布给所有的监听者、publishEvent()
要找到这个方法,我们需要先进入refresh()中的finishRefresh()






publishEvent()中将给定的事件发布给所有的监听者


如果存在父容器,则再次调用publishEvent()方法
getApplicationEventMulticaster().multicastEvent()
这个方法是获取事件广播器来发布事件的


getApplicationEventMulticaster()


这里的this.applicationEventMulticaster一般(用户不自定义的话)为默认的SimpleApplicationEventMulticaster实现类(这个实现类是在初始化事件监听多路播放器的时候,如果用户没有自定义多路播放器,设置的默认类)
multicastEvent()
在这个方法中会遍历所有注册的监听器
每次循环依次调用invokeListener(),判断该监听器是否能处理当前类型的事件


找到SimpleApplicationEventMulticaster实现类




从上图可以看得出,无论executor是否为空,都会调用invokeListener()方法,executor不为空,则使用executor调用监听器,否则直接调用监听器
invokeListener()
方法中先获取此广播器的当前错误处理程序,如果该错误处理程序不为空,则使用带错误处理的方式调用doInvokeListener()方法,否则,直接调用doInvokeListener()方法即可


doInvokeListener()
doInvokeListener()方法实际执行除法监听器的方法(你看它是do开头的嘛)
触发的是监听器的onApplicationEvent()方法,将给定的事件event当作参数传入函数




各个监听器就是通过重写这个方法来时实现不同逻辑的


至此,当前遍历的单个监听器的逻辑执行完毕,返回multicastEvent()方法中的遍历逻辑中继续判断集合中的下一个监听器
遍历结束,集合中监听器们的处理事件流程结束
(。・ω・。)ノ
回复

使用道具 举报

1

主题

5

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2025-2-6 08:02:02 | 显示全部楼层
佩服佩服!
回复

使用道具 举报

0

主题

8

帖子

13

积分

新手上路

Rank: 1

积分
13
发表于 2025-2-7 17:54:01 | 显示全部楼层
秀起来~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver| 手机版| 小黑屋| 零维护

GMT+8, 2025-4-19 11:49 , Processed in 0.196421 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2020, LianLian.

快速回复 返回顶部 返回列表