码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • 【Spring源码】14. 消息多播器(观察者模式)


    【Spring源码系列- IOC】

    1

    【Spring源码】0.安装Gradle环境

    2

    【Spring源码】1.下载与编译_pom relocation to an other version number is not f

    3

    【Spring源码】2.试个水先~Debug找到传说中的三级缓存(图解向,堆图预警)

    4

    【Spring源码】3. xml文件如何转换成BeanDefinition(主要涉及prepareRefresh()+ obtainFreshBeanFactory()两个函数,图解向,堆图预警)_spring xml转bean

    5

    【Spring源码】4. 自己搞个标签?~自定义标签保姆级全过程(图解向,堆图预警)

    6

    【Spring源码】5.spring的bean工厂准备工作(prepareBeanFactory(beanFactory)

    7

    【Spring源码】6. Spring扩展自定义属性编辑器保姆级教程

    8

    【Spring源码】7. 如何添加自定义的BeanFactoryPostProcessor

    9

    【Spring源码】8. 捋下invokeBeanFactoryPostProcessors()主要处理流程

    10

    【Spring源码】9. 超级重要的ConfigurationClassPostProcessor

    11

    【Spring源码】10. 递归调用的processConfigurationClass()方法

    12

    【Spring源码】11. 我是注解类不?checkConfigurationClassCandidate()注解类判断方法详解

    13

    【Spring源码】12. 注册bean处理器registerBeanPostProcessors()

    14

    【Spring源码】13. 国际化处理initMessageSource()源码解析

    【补充内容】【保姆级】SpringBoot项目中的i18n国际化

    15

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

    【补充内容】【保姆级示例向】观察者模式

    16

    【Spring源码】15. Bean的创建过程(1.概述篇)

    17

    【Spring源码】16. Bean的创建过程(2)

    18

    【Spring源码】17.创建Bean这篇认真的@(・●・)@

    【补充内容】

    【保姆级·创建对象】如何通过Supplier创建对象

    【保姆级·创建对象】如何通过factory-method创建对象

    【保姆级·创建对象】如何利用resolveBeforeInstantiation()在预处理阶段返回一个Bean的实例对象

    19

    【Spring源码】18. factory-method创建对象关键函数详解:instantiateUsingFactoryMethod()

    20

    【Spring源码】19. 没合适的构造器?找determineCandidateConstructors()!

    21

    【Spring源码】20. MergedBeanDefinitionPostProcessor修改/合并bean定义

    【补充内容】

    【保姆级】@PostConstruct & @PreDestroy使用示例

    【Spring源码】AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解

    【Spring源码】CommonAnnotationBeanPostProcessor.postProcessMergedBeanDefinition()详解

    22

    【Spring源码】21. 初探循环依赖

    【补充内容】

    【保姆级】手把手Debug循环依赖的整体流程

    【实践向】当移除了三级缓存……

    【分析向】没有三级缓存会导致什么?

    【Spring源码】插播一个创建代理对象的wrapIfNecessary()方法

    23

    【Spring源码】22. 属性填充populateBean()详解

    【补充内容】

    【Spring源码】自动注入·名称:autowireByName()详解

    【Spring源码】自动注入·类型:autowireByType()详解

    【Spring源码】属性值的解析与赋值:populateBean().applyPropertyValues()

    【保姆级】超超超简单的自定义注解实现@Autowired同款功能

    24

    【Spring源码】23. 执行初始化逻辑:initializeBean()

    本文目录

    观察者模式

    事件驱动

    逻辑流程

    代码执行流程

    消息多播器相关方法详解

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

    初始化其他bean、onRefresh()

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

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

    getApplicationEventMulticaster().multicastEvent()

    ​getApplicationEventMulticaster()

    multicastEvent()

    invokeListener()

    ​doInvokeListener()


    本文主要涉及三个方法 initApplicationEventMulticaster()、onRefresh()、registerListeners()

    观察者模式

    先简单介绍下观察者模式

    观察者模式是指当一个行为发生时,一个用户传递信息,另一个用户接收信息并作出相应的处理,行为和接受者之间没有直接的耦合关系(《重学Java设计模式》)

    比较常见应用于MQ(Message Queue,消息队列)服务中

    分为被观察者和观察者

    • 被观察者的对象存在一个集合中,执行不同方法时,调用观察者的方法进行处理

    • 观察者则在看到被观察者的某种行为后执行相应的行为

    事件驱动

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

    • 事件

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

    • 监听器(观察者)

      • 可能存在多个

      • 接受不同的事件来做不同的处理工作

    • 多播器

      • 广播事件

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

    • 事件源

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

    逻辑流程

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

    1. 事件源发布不同的事件

    2. 发布事件后,执行多播器的方法来进行事件广播操作,触发具体的监听器

    3. 监听器接收到具体的事件后,会验证与自己的逻辑是匹配

    4. 匹配:处理

    5. 不匹配:不做任何操作

    代码执行流程

    1. 准备多个事件

    2. 初始化多播器(需要包含一个存放监听器的集合)

    3. 准备监听器

    4. 将准备好的监听器注册到多播器中(放到多播器的几何中,方以便后续多播器进行广播通知)

    5. 事件发布,触发多播器

    消息多播器相关方法详解

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

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

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

    1. 获取当前Bean工厂,一般是DefaultListableBeanFactory

    2. 判断当前bean工厂里是否包含BEAN_NAME为applicationEventMulticaster(自定义事件监听多播器)的Bean

    3. 有的话获取

    4. 没有的话,设置默认的(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()

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

    1. 遍历应用程序中存在的监听器集合,并将对应的监听器添加到监听器的多路广播器中(此处添加的是对象)

    2. 从容器中获取所有实现了ApplicationListener接口的BeanDefinition的BeanName,放入集合ApplicationListenerBeans中(此处添加的是名称,这种方式后面一般会通过beanFactory.getBean(listenerBeanName, ApplicationListener.class获取到其对象))

    3. 发布监听器集合(早期的)

    ​将给定的事件发布给所有的监听者、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()方法中的遍历逻辑中继续判断集合中的下一个监听器 遍历结束,集合中监听器们的处理事件流程结束 (。・ω・。)ノ🎉🎉🎉

  • 相关阅读:
    在SQL语句里使用正则表达式,因该怎么使用
    WPF:xaml语言【万字基础】
    Python中给字典排序的三种方法(有一种你绝对没见过)
    JS基础----call和apply方法、代理Proxy的使用、JS中defineProperty用法
    【C++】编程题遇到行数不固定的字符串(以逗号或空格分割)
    git常用操作-仓库创建、初始化、拉取项目
    C++ day2
    智能合约编写高级篇(二)区块哈希介绍
    第 361 场 LeetCode 周赛题解
    通义灵码,降临博客园
  • 原文地址:https://blog.csdn.net/aqin1012/article/details/126644051
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号