近期疫情形势严峻,情形不容乐观,周末也不敢出去浪了,躲在家里“葛优躺”。闲来无事,又翻了遍Spring
的源码。不翻不知道,一翻吓一跳,之前翻过的源码已经吃进了肚子里,再见亦是陌生人。
个人建议:为了以后能快速的捡起某个知识点,最好的方法还是形成文档,下次有遗漏的时候,直接读文档,按之前的思路捋一遍,“干净又卫生”。
[之前的文章] 中我们已经介绍过如何在项目中快速上手“事件通知机制”,相信大家已经掌握了。但是我们作为高级javaer
,要知其然,更要知其所以然。今天就带大家从源码的角度来分析一下广播与监听的底层实现原理。
源码导入[教程] 也给你准备好了,不来试试吗?
版本号:spring-framework-5.0.x
为了实现广播与监听的功能,Spring
为我们提供了两个重要的函数式接口:ApplicationEventPublisher
和ApplicationListener
。前者的publishEvent()
方法为我们提供了发送广播的能力;后者的onApplicationEvent()
方法为我们提供了监听并处理事件的能力。
接下来我们就来分析一下spring
是如何运用这两种能力的。
不知道大家对单例对象的初始化调用过程是否熟悉?主要调用方法流程如下:
applyBeanPostProcessorsBeforeInitialization
方法会去遍历该工厂创建的所有的Bean
后置处理器,然后去依次执行后置处理器对应的postProcessBeforeInitialization
方法。
在该方法的实现类中我们看到了两个熟悉的类名
不知道大家还记得不,这俩类是在beanFactory
的准备工作过程中添加的两个bean
的后置处理器,所以这个地方会依次去执行这两个类中的实现方法。
由于蓝框中类的实现方法是默认实现按照原样返回的给定的bean
,所以此处不用过多分析,我们重点来看下红框中类的方法实现。
该方法中最重要的是invokeAwareInterfaces
方法,它的作用是检测对应的bean
是否实现了某个Aware
接口,如果实现了的话就去进行相关的调用。
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
我们发现在invokeAwareInterfaces
方法中出现了如上代码,这不就是和广播发送相关的吗?所以只要我们写一个类来实现ApplicationEventPublisherAware
接口,就可以在该bean
中注入一个ApplicationEventPublisher
对象,也就获得了发送广播的能力。
applyBeanPostProcessorsAfterInitialization
方法也会去遍历该工厂创建的所有的Bean
后置处理器,然后去依次执行后置处理器对应的postProcessAfterInitialization
方法。
同样的,该方法的实现类中也有ApplicationContextAwareProcessor
和ApplicationListenerDetector
两个类,但是不同的是,前者的类的实现方法是默认实现按照原样返回的给定bean
,而后者做了相关的处理。
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
上述代码是将实现了ApplicationListener
接口的bean
添加到监听器列表中,最终是保存在AbstractApplicationEventMulticaster
的成员变量defaultRetriever
的集合applicationListeners
中。
猜想:当发送广播消息时,就直接找到集合中的这些监听器,然后调用每个监听器的
onApplicationEvent
方法完成事件的处理。
在refresh()
的finishRefresh()
方法中,
publishEvent(new ContextRefreshedEvent(this));
发送一条事件类型为ContextRefreshedEvent
的广播消息,用来代表Spring
容器初始化结束。通过分析发现,该方法中最主要的就是如下代码:
//真正的广播交给 applicationEventMulticaster 来完成
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
refresh()
的initApplicationEventMulticaster()
将applicationEventMulticaster
初始化为SimpleApplicationEventMulticaster
在实现类SimpleApplicationEventMulticaster
的方法中,会找到已注册的ApplicationListener
列表,然后分别调用invokeListener
方法(将监听和事件作为参数传到方法并执行的过程就是发送广播的过程)。
底层调用的是listener.onApplicationEvent(event);
方法,也就是各个监听实现类单独处理广播消息的逻辑。
看到这儿,你是不是已经发现了:消息类型和监听器的绑定发生在广播过程中。接下来就让我们去一探究竟
我们看一下multicastEvent()
方法中的getApplicationListeners(event, type)
方法。
在该方法中,用到了ConcurrentHashMap
类型的缓存retrieverCache
,所以每种类型的事件在广播的时候会触发一次绑定操作。它的key由事件的来源和类型确定,它的value中就包含了由事件来源和类型所确定的所有监听列表。
其中绑定的逻辑就出现在retrieveApplicationListeners
方法中,大家可以去源码中查看。
纸上得来终觉浅,绝知此事要躬行。为了更好地理解广播与监听的流程,我们当然得用实战来加以辅佐!
public class MyEvent extends ApplicationContextEvent {
public MyEvent(ApplicationContext source) {
super(source);
}
}
@Component
public class MyPublisher implements ApplicationEventPublisherAware, ApplicationContextAware {
private ApplicationEventPublisher applicationEventPublisher;
private ApplicationContext applicationContext;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
//发送广播消息
public void publishEvent(){
System.out.println("我要开始发送消息了。。。");
MyEvent myEvent = new MyEvent(applicationContext);
applicationEventPublisher.publishEvent(myEvent);
}
}
MyPublisher
实现了ApplicationEventPublisherAware
接口 ,在spring
初始化(见上文中的invokeAwareInterfaces
)的时候会回调setApplicationEventPublisher
方法,获取到初始化(添加bean
后置处理器ApplicationContextAwareProcessor
)时的AbstractApplicationContext
,而AbstractApplicationContext
又间接实现了ApplicationEventPublisher
而获得发送能力。真正执行的是 AbstractApplicationContext
类中的 publishEvent
方法。
@Component
public class MyEventListener implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("我监听到你的消息了");
}
}
MyEventListener
实现了ApplicationListener
接口,在spring
初始化(见上文中的addApplicationListener
)的时候会添加到applicationListeners
中,在执行publishEvent
方法时就会走MyEventListener
中的onApplicationEvent
方法。
@RestController
@RequestMapping("/demo")
public class DemoTest {
@Autowired
private MyPublisher myPublisher;
@RequestMapping("/test")
public void test() {
myPublisher.publishEvent();
}
}
访问127.0.0.1:8008/demo/test
就可以发送广播了,发送与监听内容如下:
我要开始发送消息了。。。
我监听到你的消息了
看到这儿,相信你己经完全掌握了广播与监听的精髓了,赶快实践起来吧。
本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/9JJMq5l9sfCUz2_QhaL5Jg
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。